1. GTK概念
GTK+是一种跨平台的图形工具包,它可以很方便的制作图形交互界面(GUI)。
官网:http://www.gtk.org/
2. Linux安装
1、测试本地环境是否安装或安装成功:pkg-config --cflags --libs gtk±2.0
若安装成功后执行此语句的现象为:
-pthread -I/usr/local/include/gio-unix-2.0/ -I/usr/local/include/atk-1.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/include/gtk-2.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/freetype2 -I/usr/include/pixman-1 -I/usr/include/libpng12
说明成功
2、安装命令:sudo apt-get install libgtk2.0*
(此处用的GTK+2.0,目前最新版本为4.1,命令相同)
3. 开启GTK+之旅
1、GTK+程序的基本的框架
#include <gtk/gtk.h> // 头文件;
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv); // 初始化;
/*
* 我们所写的代码段;
*/
gtk_main(); // 主事件循环;
return 0;
}
说明:
(1)<gtk/gtk.h>头文件包含了GTK+的所有控件、变量、函数和结构的声明;
(2)gtk_init():此函数必须在控件定义之前使用,参数由命令行中解析出来并送到该程序中。主要作用是设立GTK+运行环境,自动完成一些必要的初始化工作;
(3)自定义代码段:创建窗口等控件,并且使其显示并赋值功能等;
(4)gtk_main():程序运行停在此处等待事件(如键盘事件或鼠标事件等)的发生,等待用户来操作窗口,这个函数在所有的GTK+程序中都要调用。
2、创建窗口控件的基本API
(1) 创建窗口
原型 |
GtkWidget *gtk_window_new(GtkWindowType type);
|
---|---|
输入参数 |
GtkWindowType是一个枚举,有两种情况:
GTK_WINDOW_TOPLEVEL:有边框,顶层窗口; GTK_WINDOW_POPUP: 没边框,弹出式窗口。 |
返回值 |
window (GtkWidget类型)
|
(2) 为窗口设置标题
原型 |
void gtk_window_set_title(GtkWindow *window, const gchar *title);
|
---|---|
输入参数 |
window:创建窗口返回值,在此需强转为 (GtkWindow *) 类型;
title: 自定义字符串。 |
返回值 |
无
|
(3) 窗口大小设置
原型 |
void gtk_widget_set_size_request(GtkWidget *widget,gint width,gint height);
|
---|---|
输入参数 |
widget:窗口句柄;
width、height: 窗口宽度和高度。 |
返回值 |
无
|
(4) 窗口伸缩设置
原型 |
void gtk_window_set_resizable(GtkWindow *window, gboolean resizable);
|
---|---|
输入参数 |
window:创建窗口返回值,在此需强转为 (GtkWindow *) 类型;
resizable: bool值,FALSE 为不可伸缩。 |
返回值 |
无
|
(5) 窗口在显示器位置的设置
原型 |
void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position);
|
---|---|
输入参数 |
window:创建窗口返回值,在此需强转为 (GtkWindow *) 类型;
position常用有4种情况: GTK_WIN_POS_NONE: 不固定; GTK_WIN_POS_CENTER: 居中; GTK_WIN_POS_MOUSE: 出现在鼠标位置; GTK_WIN_POS_CENTER_ALWAYS: 窗口总是居中。 |
返回值 |
无
|
(6) 显示控件
显示单一控件 |
void gtk_widget_show(GtkWidget *widget);
|
---|---|
显示所有控件 |
void gtk_widget_show_all(GtkWidget *widget);
|
隐藏所有控件 |
void gtk_widget_hide_all(GtkWidget *widget);
|
输入参数 |
widget:窗口控件,其余控件添加其中
|
返回值 |
无
|
示例:
#include <gtk/gtk.h>
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title((GtkWindow *)window,"hello world");
gtk_window_set_position((GtkWindow *)window,GTK_WIN_POS_MOUSE);
gtk_widget_show(window);
gtk_main();
return 0;
}
效果:
3、编译:
gcc demo.c -o demo `pkg-config --cflags --libs gtk±2.0`(反单引号部分必须,其自动获得预处理参数,如宏定义、头文件的位置,自动获得链接参数,如库依赖的其他库的位置、文件名及其他一些链接参数)
或写Makefile代替:
CC = gcc
MAINC = demo.c
EXEC = demo
CFLAGS = `pkg-config --cflags --libs gtk+-2.0`
main:
$(CC) $(MAINC) -o $(EXEC) $(CFLAGS)
clean:
rm $(EXEC) -rf
4、控件的介绍
(1)控件是对数据和方法的封装。控件有自己的属性和
方法。属性是指控件的特征。方法是指控件的一些
简单而可见的功能;
(2)控件的分类:容器控件,非容器控件;
(3)容器控件:它可以容纳别的控件。容器控件分为两
类,一类只能容纳一个控件,如窗口,按钮;另一
类能容纳多个控件,如布局控件;
(4)非容器控件:它不可以容纳别的控件,如标签、行
编辑。
5、创建按钮API
(1)创建一个带内容的按钮
原型 |
GtkWidget *gtk_button_new_with_label(const gchar *label );
|
---|---|
输入参数 |
label :自定义字符串
|
返回值 |
button:按钮控件 (GtkWidget类型)
|
(2)获得按钮上面的文本内容
原型 |
const gchar *gtk_button_get_label(GtkButton *button );
|
---|---|
输入参数 |
button:需强转为(GtkButton *)类型
|
返回值 |
按钮上的字符串
|
强制转换控件类型,也可以写为:GTK_BUTTON(button),其余控件写法类似
#define GTK_BUTTON(x) (GtkButton *)x
(3)把控件添加到窗口容器里
原型 |
void gtk_container_add(GtkContainer *container, GtkWidget *widget);
|
---|---|
输入参数 |
container:窗口容器,需强转为(GtkContainer*)类型;
widget:按钮控件 |
返回值 |
无
|
6、给控件设置信号回调函数
窗口关闭时触发的常用信号:destroy, delete-event
操作按钮触发的常用信号:clicked, pressed,released
(1)信号与回调函数的连接
原型 |
gulong g_signal_connect( gpointer instance,const gchar *detailed_signal,GCallback c_handler,gpointer data );
|
---|---|
输入参数 |
instance: 信号的发出者;
detailed_signal:要连接信号的名称; c_handler: 回调函数的名称,需要用G_CALLBACK()进行转换; data: 传递给回调函数的参数 |
返回值 |
整型数据
|
(2)信号连接函数的写法及回调函数的定义
g_signal_connect(button, “pressed”,G_CALLBACK(callback), NULL);
原型 |
void callback( GtkButton *button, gpointer user_data );
|
---|---|
输入参数 |
button: 信号的发出者,需强转(GtkButton *)类型;
user_data: 传给回调函数的数据 |
返回值 |
无
|
示例:
#include <gtk/gtk.h>
// 按钮按下的处理函数, gpointer 相当于 void *
void deal_pressed(GtkButton *button, gpointer user_data)
{
// 获得按钮的文本信息
const gchar *text = gtk_button_get_label( button );
// g_print() 相当于C语言的 printf(), gchar相当于char
g_print("button_text = %s; user_data = %s\n", text, (gchar *)user_data);
}
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
// 设置窗口边框的宽度(窗口里的控件与窗口边框间隔为50)
gtk_container_set_border_width(GTK_CONTAINER(window),50);
/* 信号连接函数当窗口关闭时,窗口会触发destroy信号,信号回调;
* 当窗口关闭时,窗口会触发destroy信号,
* 自动调用gtk_main_quit()结束程序运行
* 窗口关闭时触发的常用信号:destroy、delete-event;
*/
g_signal_connect(window,"destroy",G_CALLBACK(gtk_main_quit),NULL);
// 创建按钮, 文本信息为"Hello Gtk+";
GtkWidget *button = gtk_button_new_with_label("Hello GTK+");
// 获得按钮的内容;
const char *str = gtk_button_get_label(GTK_BUTTON(button));
printf("-> str = %s\n",str);
// 把按钮添加到窗口容器;
gtk_container_add(GTK_CONTAINER(window),button);
/* 按钮按下(pressed)后会自动调用deal_pressed()
* "is pressed"是传给deal_pressed()的数据
* 操作按钮触发的常用信号:clicked、pressed、released;
*/
g_signal_connect(button, "pressed", G_CALLBACK(deal_pressed), "is pressed");
// 显示控件有两种方法:逐个显示,全部显示;
// gtk_widget_show(button);
// gtk_widget_show(window);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
效果
7、布局
(1)定义:设定控件在整个窗口中的位置和尺寸;
(2)常用布局方式:
-> 水平布局 GtkHBox
-> 垂直布局 GtkVBox
-> 表格布局 GtkTable
-> 固定布局 GtkFixed
(3)创建水平布局
原型 |
GtkWidget *gtk_hbox_new(gboolean homogeneous, gint spacing);
|
---|---|
输入参数 |
homogeneous:容器内控件是否均衡排放(大小一致);
spacing: 控件之间的间隔 |
返回值 |
hbox:水平布局控件
|
(4)创建垂直布局
原型 |
GtkWidget *gtk_vbox_new(gboolean homogeneous, gint spacing);
|
---|---|
输入参数 |
homogeneous:容器内控件是否均衡排放(大小一致);
spacing: 控件之间的间隔 |
返回值 |
vbox:垂直布局控件
|
(5)创建标签
原型 |
GtkWidget *gtk_label_new(const gchar *str);
|
---|---|
输入参数 |
str:标签字符串
|
返回值 |
label:标签控件
|
(6)设置标签内容
原型 |
void gtk_label_set_text(GtkLabel *label, const gchar *str);
|
---|---|
输入参数 |
label:标签控件,需强转(GtkLabel *)类型;
str:自定义字符串 |
返回值 |
无
|
(7)获得标签内容
原型 |
const gchar *gtk_label_get_label(GtkLabel *label );
|
---|---|
输入参数 |
label:标签控件,需强转(GtkLabel *)类型
|
返回值 |
标签内容
|
(8)创建表格布局
原型 |
GtkWidget *gtk_table_new( guint rows, guint columns, gboolean homogeneous );
|
---|---|
输入参数 |
rows: 行数;
coumns: 列数; homogeneous:容器内表格的大小是否一致。 |
返回值 |
table:布局控件
|
(9)添加控件到表格布局容器中
原型 |
void gtk_table_attach_defaults(GtkTable *table,
GtkWidget *widget, guint left_attach, guint right_attach, guint top_attach, guint bottom_attach ); |
---|---|
输入参数 |
table: 要容纳控件的容器 ;
widget: 被容纳控件; 后四个参数为控件摆放的坐标。 |
返回值 |
无
|
坐标规则:
(10)创建固定布局容器
原型 |
GtkWidget *gtk_fixed_new(void);
|
---|---|
输入参数 |
无
|
返回值 |
fixed:固定布局控件
|
(11)创建固定布局容器
原型 |
GtkWidget *gtk_fixed_new(void);
|
---|---|
输入参数 |
无
|
返回值 |
无
|
(12)添加控件到固定布局容器中
原型 |
void gtk_fixed_put( GtkFixed *fixed,GtkWidget *widget,gint x,gint y );
|
---|---|
输入参数 |
fixed:要容纳控件的容器;
widget:被容纳控件; x,y: 控件摆放位置的起点坐标。 |
返回值 |
无
|
8、综合布局
综合布局是指布局容器的嵌套使用。
(1)创建行编辑
原型 |
GtkWidget *gtk_entry_new(void);
|
---|---|
输入参数 |
无
|
返回值 |
entry:行编辑控件
|
(2)行编辑显示模式
原型 |
void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible );
|
---|---|
输入参数 |
entry:行编辑控件,需强转(GtkEntry *)类型;
visible:bool值,FALSE为密码模式 |
返回值 |
无
|
(3)获得行编辑文本内容
原型 |
const gchar *gtk_entry_get_text(GtkEntry *entry );
|
---|---|
输入参数 |
entry:行编辑控件,需强转(GtkEntry *)类型
|
返回值 |
行控件的内容
|
(4)获得行编辑文本内容
原型 |
void gtk_entry_set_text(GtkEntry *entry,const gchar *text);
|
---|---|
输入参数 |
entry:行编辑控件,需强转(GtkEntry *)类型;
text:要设置的内容。 |
返回值 |
无
|
(5)触发信号:activate,按回车键触发
示例:
#include <gtk/gtk.h>
// 按Enter,获取行编辑的内容;
void enter_callback( GtkWidget *widget, gpointer entry )
{
const gchar *entry_text;
// 获得文本内容;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
printf("Entry contents: %s\n", entry_text);
}
int main( int argc, char *argv[] )
{
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "GTK Container");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// 添加垂直布局,控件均衡摆放,控件间距为5;
GtkWidget *vbox = get_vbox_new(TRUE,5);
gtk_container_add(GTK_CONTAINER(window),vbox);
// 创建行编辑;
GtkWidget *entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(vbox),entry);
// 设置行编辑显示最大字符长度;
gtk_entry_set_max_length(GTK_ENTRY(entry),100);
// 设置内容;
gtk_entry_set_text(GTK_ENTRY(entry),"Hello World");
// 设置密码模式;
gtk_entry_set_visibility(GTK_ENTRY(entry),FALSE);
/* 如果我们想在用户输入文本时进行响应,可以为activate设置回调函数;
* 当用户在文本输入构件内部按回车键时引发Activate信号;
*/
g_signal_connect(entry,"activate",G_CALLBACK(enter_callback),entry);
// 创建水平布局容器;
GtkWidget *hbox = gtk_hbox_new(TRUE,10);
gtk_container_add(GTK_CONTAINER(vbox),hbox);
// 创建 button1、button2、button3 并加入到水平布局;
GtkWidget *button1 = gtk_button_new_with_label("button1");
gtk_container_add(GTK_CONTAINER(hbox),button1);
GtkWidget *button2 = gtk_button_new_with_label("button2");
gtk_container_add(GTK_CONTAINER(hbox),button2);
GtkWidget *button3 = gtk_button_new_with_label("button3");
gtk_container_add(GTK_CONTAINER(hbox),button3);
// 创建关闭按钮,添加到垂直布局;
GtkWidget *button_close = gtk_button_new_with_label("close");
gtk_container_add(GTK_CONTAINER(vbox),button_close);
g_signal_connect(button_close,"clicked",G_CALLBACK(gtk_main_quit),NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
效果: