Linux下图形界面编程——GTK+元件、信号与回调函数
GTK界面基本元件
需要包含#include<gtk/gtk.h>
窗口
1. 新建窗口
gtk_window_new()可以建立一个GTK+窗口,函数原型如下:
GtkWidget * gtk_window_new (GtkWindowType type);
返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。
参数type是一个表示窗口状态的常量,可能取值有以下两种:
- GTK_WINDOW_TOPLEVEL:表示该窗口是一个正常的窗口,可以最小化。
- GTK_WINDOW_POPUP:表示该窗口是一个弹出式的窗口,不可以最小化。
2. 设置窗口标题
gtk_window_set_title()函数用于设置窗口标题,使用方法如下:
void gtk_window_set_title(GtkWindow *window, gchar *title);
参数window指定将要添加标题的窗口,title表示需要设置的标题。需要注意title指向的字符串必须是英文字符,若需要显示中文字符,则需要使用g_locale_to_utf8()函数进行批注。
3. 设置窗口大小与位置
窗口大小指的是窗口的宽度和高度,用gtk_widget_set_usize()函数设置一个窗口的初始化大小。窗口位置指的是窗口的左上顶点到屏幕左边和顶边的距离,可以用gtk_widget_set_uposition()函数来设置一个窗口的初始位置。这两个函数的原型为:
void gtk_widget_set_usize(GtkWidget *widget, gint width, gint height);
void gtk_widget_set_uposition(GtkWidget *widget, gint x, gint y);
参数widget用于指定将要进行设置的窗口,width表示窗口的宽度,height表示窗口的高度;x表示窗口的左边距,即左上顶点的x坐标,y表示窗口的上边距,也是窗口的左上顶点的y坐标。
显示窗口需要调用gtk_widget_show()函数。
标签
1. 新建标签
gtk_label_new()可以建立一个标签,函数原型如下:
GtkWidget * gtk_label_new (gchar *text);
返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。
参数text表示标签需要显示的内容
2. 将标签添加到窗口
GTK+窗口中,除了window窗口外,其他元件都必须放置在一个容器中。新建的标签并不能直接显示,需要放在一个窗口元件中。gtk_container_add()函数作用是把一个元件放置在另一个元件窗口(窗口)中,函数原型如下:
void gtk_container_add (GtkContainer *container, GtkWidget *widget);
参数container是一个父级容器指针,widget是需要放置的元件指针。
3. 设置与获取标签文本
在程序中,可以用gtk_label_get_text()函数获取一个标签的文本。使用gtk_label_set_text()函数来设置一个标签的文本。这两个函数的原型为:
const char* gtk_label_get_text (GtkLabel *label);
void gtk_label_set_text (GtkLabel *label, gchar *text);
第一个函数返回:若成功则返回标签文本的字符串指针,失败则返回NULL。
函数中参数label是一个指向标签的指针,text表示标签需要设置的文本。
显示标签需要调用gtk_widget_show()函数
按钮
1. 新建按钮
gtk_button_new_with_label()可以建立一个带标签的按钮,函数原型如下:
GtkWidget * gtk_button_new_with_label (gchar *label);
返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。
参数label表示按钮需要显示的内容
2. 设置与获取按钮的标签
gtk_button_get_label()函数可以获取一个按钮的标签。gtk_button_set_label()函数可以设置一个按钮的标签。这两个函数的原型为:
const gchar* gtk_button_get_label (GtkButton *button);
void gtk_button_set_label (GtkButton *button, const gchar *label);
第一个函数返回:若成功则返回按钮标签内容的字符串指针,失败则返回NULL。
函数中参数button是一个指向按钮的指针,label表示按钮的标签内容。按钮的使用通常伴随着GTK+信号与事件的产生。
显示按钮需要调用gtk_widget_show()函数
文本框
1. 新建文本框
gtk_entry_new()可以建立一个文本框,函数原型如下:
GtkWidget * gtk_entry_new (void);
返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。
另一个建立文本框的函数为:
GtkWidget * gtk_entry_new_with_max_length (gint max);
返回同上,参数max用来表示这个文本框最多可以输入的字节数。
2. 设置与获取文本框数据
gtk_entry_get_text()函数gtk_entry_set_text()函数可以得到和设置文本框的数据。这两个函数的原型为:
const gchar* gtk_entry_get_text (GtkEntry *entry);
void gtk_entry_set_text (GtkEntry *entry, const gchar *text);
第一个函数返回:若成功则返回按钮标签内容的字符串指针,失败则返回NULL。
函数中参数entry是一个指向文本框的指针,text表示设置到文本框中的字符串文本。
显示文本框需要调用gtk_widget_show()函数
example: 保存为entry_example.c
1 #include <gtk/gtk.h> 2 #include <stdlib.h> 3 4 5 GtkWidget *window; 6 GtkWidget *table; 7 GtkWidget *entry; 8 GtkWidget *label; 9 GtkWidget *button; 10 char text[50]; 11 12 void on_clicked(GtkWidget *widget, gpointer data) 13 { 14 strcpy(text, gtk_entry_get_text (GTK_ENTRY(entry))); 15 printf("您输入到字符串是:%s:\n",text); 16 } 17 18 int main(int argc, char* argv[]) 19 { 20 gtk_init(&argc, &argv); 21 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 22 //设置窗口标题 23 gtk_window_set_title(GTK_WINDOW(window), g_locale_to_utf8("文本框的使用", -1, NULL, NULL, NULL)); 24 //定义3行2列的表格,单元格大小根据单元格元件大小自动调整 25 table = gtk_table_new(3, 2, FALSE); 26 label = gtk_label_new(g_locale_to_utf8("请在这里输入文本", -1, NULL, NULL, NULL)); 27 //新建有字数限制的文本框,最多输入50个字符 28 entry = gtk_entry_new_with_max_length(50); 29 //新建提交按钮 30 button = gtk_button_new_with_label(g_locale_to_utf8("提交", -1, NULL, NULL, NULL)); 31 //将表格添加到窗口中 32 gtk_container_add(GTK_CONTAINER(window), table); 33 //将三个元件分别添加到表格相应的位置 34 gtk_table_attach (GTK_TABLE(table), label, 0, 1, 0, 1, 35 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10); 36 gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 1, 2, 37 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10); 38 gtk_table_attach (GTK_TABLE(table), button, 1, 2, 2, 3, 39 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10); 40 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window); 41 gtk_widget_show_all(window); 42 gtk_main(); 43 return 0; 44 }
使用gcc编译
gcc -o entry_example entry_example.c `pkg-config --libs --cflags gtk+-2.0`
./entry_example
运行结果为
在文本框中输入"hello world!"并点击提交,会在shell中显示
界面布局元件
GTK+的容器都是二进制的,也就是说每个容器只能放置一个元件,如果想在一个窗口中放置多个元件,则需要使用表格、窗格等有多个单元格的容器。
表格
1.表格的建立
在窗口中使用表格,需要调用gtk_table_new()函数新建一个表格,函数原型如下:
GtkWidget *gtk_table_new(guint rows, guint columns, gboolean homogeneous);
返回:若成功则返回一个GtkWidget类型的指针,失败则放回NULL。
参数rows表示表格的行数,columns表示表格列数,类型是无符号整型。行列标号从边开始算起,如下图所示
例如,某个元件占据了上图蓝色阴影部分,则它所占格子的坐标为left为0, right为2, top为2, butoom为4。
参数homogeneous是一个布尔值,TRUE表示每个单元格大小相同,所有单元格高度和宽度和表格中最大的一个相同;FALSE表示单元格大小会根据元件大小自动调整。
表格的作用只是将窗口划分成不同的区域,并不能显示出这个表格。
函数gtk_table_attach()作用是将一个元件添加到表格中,并设置在表格的位置和填充的选项。函数原型如下:
void gtk_table_attach(GtkTable *table, GtkWidget *child, guint left_attach, guint right_attach, guint top_attach, guint buttom_attach,
GtkAttachOptions xoptions, GtkAttachOptions yoptions,
guint xpadding, guint ypadding);
参数含义和作用:
- table:容器表格的指针。
- child:需要添加的元件的指针。
- left_attach,right_attach:分别表示元件的左边是表格x方向的第几条边,右边是表格x方向的第几条边。
- top_attach, buttom_attach:分别表示元件的上边是表格y方向的第几条边,下边是表格y方向的第几条边。
- xoptions,yoptions:分别表示元件在表格中的水平方向、垂直方向的对齐方式,取值类型为GtkAttachOptions。
- xpadding,ypadding:分别表示元件与边框水平方向、垂直方向的边距。
表格可以嵌套表格。
下面为程序演示例子,保存为con_nested_table.c
1 #include<gtk/gtk.h> 2 3 int main(int argc, char *argv[]) 4 { 5 GtkWidget *window; 6 GtkWidget *table1; 7 GtkWidget *table2; 8 GtkWidget *button1; 9 GtkWidget *button2; 10 GtkWidget *entry1; 11 GtkWidget *entry2; 12 GtkWidget *entry3; 13 GtkWidget *entry4; 14 GtkWidget *label1; 15 GtkWidget *label2; 16 GtkWidget *label3; 17 GtkWidget *label4; 18 GtkWidget *label5; 19 20 gtk_init(&argc, &argv); 21 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 22 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("用户信息", -1, NULL, NULL, NULL));//设置窗口标题 23 //建立表格 24 table1 = gtk_table_new (4, 4, FALSE); 25 table2 = gtk_table_new (1, 2, FALSE); 26 //定义5个标签、2个按钮、4个文本框 27 label1 = gtk_label_new (g_locale_to_utf8("我的信息", -1, NULL, NULL, NULL)); 28 label2 = gtk_label_new (g_locale_to_utf8("用户名", -1, NULL, NULL, NULL)); 29 label3 = gtk_label_new (g_locale_to_utf8("密码", -1, NULL, NULL, NULL)); 30 label4 = gtk_label_new (g_locale_to_utf8("电子邮件", -1, NULL, NULL, NULL)); 31 label5 = gtk_label_new (g_locale_to_utf8("详细地址", -1, NULL, NULL, NULL)); 32 button1 = gtk_button_new_with_label(g_locale_to_utf8("注册", -1, NULL, NULL, NULL)); 33 button2 = gtk_button_new_with_label(g_locale_to_utf8("登录", -1, NULL, NULL, NULL)); 34 entry1 = gtk_entry_new (); 35 entry2 = gtk_entry_new (); 36 entry3 = gtk_entry_new (); 37 entry4 = gtk_entry_new (); 38 //添加表格到窗口 39 gtk_container_add(GTK_CONTAINER (window), table1); 40 //将5个元件分别添加到表格中 41 gtk_table_attach (GTK_TABLE(table1), label1, 0, 3, 0, 1, 42 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 43 gtk_table_attach (GTK_TABLE(table1), table2, 3, 4, 0, 1, 44 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 5); 45 gtk_table_attach (GTK_TABLE(table1), label2, 0, 1, 1, 2, 46 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 47 gtk_table_attach (GTK_TABLE(table1), entry1, 1, 2, 1, 2, 48 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 49 gtk_table_attach (GTK_TABLE(table1), label3, 2, 3, 1, 2, 50 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 51 gtk_table_attach (GTK_TABLE(table1), entry2, 3, 4, 1, 2, 52 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 53 gtk_table_attach (GTK_TABLE(table1), label4, 0, 1, 2, 3, 54 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 55 gtk_table_attach (GTK_TABLE(table1), entry3, 1, 4, 2, 3, 56 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 57 gtk_table_attach (GTK_TABLE(table1), label5, 0, 1, 3, 4, 58 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 59 gtk_table_attach (GTK_TABLE(table1), entry4, 1, 4, 3, 4, 60 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 61 gtk_table_attach (GTK_TABLE(table2), button1, 0, 1, 0, 1, 62 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 2, 5); 63 gtk_table_attach (GTK_TABLE(table2), button2, 1, 2, 0, 1, 64 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 2, 5); 65 gtk_widget_show_all(window); 66 gtk_main(); 67 return 0; 68 69 70 }
使用GCC编译
gcc -o con_nested_table con_nested_table.c `pkg-config --libs --cflags gtk+-2.0`
./con_nested_table
运行结果为
框
框(box)是一種不可見的widget容器。框分为纵向框和横向框。纵向框在垂直方向堆积元件,横向框沿水平方向堆积元件。
1.框的建立
使用gtk_vbox_new函数建立纵向框,使用gtk_hbox_new函数建立横向框。函數原型爲:
GtkWidget *gtk_hbox_new(gboolean homogeneous,gint spacing);
GtkWidget *gtk_vbox_new(gboolean homogeneous,gint spacing);
参数:
- homogeneous:子构件是否具有同样的大小
- spacing
:
子构件间的距离
建立框後,需要調用gtk_container_add()函數將這個框添加到窗口中。
2.框中添加元件
可以使用gtk_box_pack_start函数或gtk_box_pack_end函数将构件放到组装盒中。前者從左到右、從上到下將元件放入框容器,而後者從右到左,從下到上將元件放入框容器。其原型爲:
void gtk_box_pack_start(GtkBox *box, GtkWidget *child, gboolean expend, gboolean fill, guint padding);
void gtk_box_pack_end(GtkBox *box, GtkWidget *child, gboolean expend, gboolean fill, guint padding);
参数:
- box:框的名称
- child:子构件的名称
- expend: 构件周围是否还有可扩充的空间
- fill:构件是否需要充分利用构件周围空间
- padding:构件周围要保留多少个填充的像元
下面是使用垂直框的程序例子,保存爲vbox_example.c
1 #include<gtk/gtk.h> 2 GtkWidget *window; 3 GtkWidget *table; 4 GtkWidget *vbox; 5 GtkWidget *button; 6 GtkWidget *label; 7 GtkWidget *entry; 8 char text[50]; 9 char text1[50]; 10 char a[50]; 11 int i = 0; 12 13 //定义信号回调函数 14 void on_clicked(GtkWidget *widget, gpointer data) 15 { 16 ++i; 17 gcvt((float)i, 3, text); 18 strcat(text, ":"); 19 //获取文本框内容,并将其复制到text字符串数组中 20 strcpy(text1, gtk_entry_get_text(GTK_ENTRY(entry))); 21 strcat(text, text1); 22 strcat(a, "\n"); 23 strcat(a, text); 24 gtk_label_set_text(GTK_LABEL(label), a); 25 } 26 27 int main(int argc, char *argv[]) 28 { 29 30 gtk_init(&argc, &argv); 31 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 32 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("我也来评论", -1, NULL, NULL, NULL));//设置窗口标题 33 //设置窗口边框 34 gtk_container_border_width(GTK_CONTAINER(window), 5); 35 vbox = gtk_vbox_new (FALSE, 10); 36 //建立表格 37 table = gtk_table_new (2, 2, FALSE); 38 //定义标签、按钮、文本框 39 label = gtk_label_new (g_locale_to_utf8("评论内容", -1, NULL, NULL, NULL)); 40 41 button = gtk_button_new_with_label(g_locale_to_utf8("发表评论", -1, NULL, NULL, NULL)); 42 43 entry = gtk_entry_new (); 44 //添加表格到窗口 45 gtk_container_add(GTK_CONTAINER (window), vbox); 46 gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, FALSE, 5); 47 gtk_box_pack_start (GTK_BOX(vbox), table, TRUE, FALSE, 5); 48 //将元件分别添加到表格中 49 gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 0, 1, 50 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 51 gtk_table_attach (GTK_TABLE(table), button, 1, 2, 1, 2, 52 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 0); 53 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window); 54 gtk_widget_show_all(window); 55 gtk_main(); 56 return 0; 57 }
使用GCC编译
gcc -o vbox_example vbox_example.c `pkg-config --libs --cflags gtk+-2.0`
./vbox_example
运行结果为
其他常用元件
1進度條、微調按鈕、組合框
1.1進度條
創建進度條要使用GtkAdjustment元件。gtk_adjustment_new()函數用於創建GtkAdjustment元件,函數原型如下:
GtkObject* gtk_adjustment_new (gdouble initial_value, gdouble lower_range, gdouble upper_range,
gdouble step_increment, gdouble page_increment, gdouble page_size);
初始化新的调节设置对象需要6个参数。下面列出参数列表。
- initial_value:当初始化时,调节设置对象中存储的值。
- lower_range:调节设置对象允许的最小值。
- upper_range:调节设置对象允许的最大值。
- step_increment:当鼠标左鍵按下時元件一次增加/減少的值。
- page_increment: 当鼠标右鍵按下時元件一次增加/減少的值
- page_size:页的大小。这个值对于GtkSpinButton没什么用处,因此它总是被设置成为和page_increment同样的值,或者0。
GTK+中创建进度条的函数调用有兩個,函數原型如下:
GtkWidget *gtk_progress_bar_new(void);
GtkWidget *gtk_progress_bar_new_with_adjustment(GtkAdjustment *adjustmen);
gtk_progress_bar_set_bar_style()函数用于设置进度条的样式,函数原型如下:
gtk_progress_bar_set_bar_style(GtkProgressBar *pbar, GtkProgressBarStyle style);
参数pbar是一个指向进度条的指針,style表示进度条的样式,取值如下:
- GTK_PROGRESS_CONTINUOUS:连续进度条
- GTK_PROGRESS_DISCRETE:条块进度条
gtk_progress_bar_set_orientation()函数用于设置进度条的方向,函数原型如下:
gtk_progress_bar_set_orientation(GtkProgressBar *pbar, GtkProgressBarOrientation orentation);
参数pbar是一个指向进度条的指針,orientation表示进度条的方向,取值如下:
- GTK_PROGRESS_LEFT_TO_RIGHT:从左往右显示
- GTK_PROGRESS_RIGHT_TO_LEFT:从右往左显示
- GTK_PROGRESS_BOTTOM_TO_TOP:从下往上显示
- GTK_PROGRESS_TOP_TO_BOTTOM:从上往下显示
gtk_progress_bar_update()函数用于更新进度条的进度状态,函数原型如下:
void gtk_progress_bar_update(GtkProgressBar *pbar, gfloat percentage);
参数pbar是一个指向进度条的指針,percentage表示进度条进度状态
1.2微调按钮
gtk_spin_button_new()用于创建微调按钮,函数原型如下:
GtkWidget *gtk_spin_button_new (GtkAdjustment *adjustment, gdouble climb_rate, guint digits);
参数climb_rate 表示微调按钮每步增加或减少的量,digits表示包含 的小数位数。
还可以使用相关的函数条用获取和设置微调按钮的值。
gtk_spin_button_get_value_as_float() 用于获取微调按钮的值,而gtk_spin_button_set_value()用于设置微调按钮的值,函数原型如下:
gtk_spin_button_get_value_as_float(GtkSpinButton *spin_button);
gtk_spin_button_set_value(GtkSpinButton *spin_button, gfloat value);
1.3组合框
组合框是文本框和列表框的组合,也称下拉列表。创建组合框要使用GList元件,用于保存列表框中将要显示的字符串。g_list_append()函数用于向GList中添加字符串,函数原型如下:
GList *g_list_append(GList *glist, char *string);
参数glist是一个指向列表框的指针,string指向将要添加至列表框中的字符串。
gtk_combo_new()函数用于创建一个组合框,函数原型如下:
GtkWidget *gtk_combo_new(void);
gtk_combo_set_popdown_strings()函数用于设置组合框中显示的字符串,函数原型如下:
gtk_combo_set_popdown_strings( GtkCombo *combo, GList *strings);
参数combo是一个指向组合框的指针,strings表示组合框中将要显示的字符串。
下面给出一个进度条、微调按钮和组合框的示例程序。control_example.c
1 #include<gtk/gtk.h> 2 3 int main(int argc, char *argv[]) 4 { 5 GtkWidget *window; 6 GtkWidget *vbox; 7 GtkWidget *label1; 8 GtkWidget *label2; 9 GtkWidget *label3; 10 GtkWidget *bar; 11 GtkWidget *spinbutton; 12 GtkObject *adjustment; 13 GList *glist; 14 GtkWidget *combo; 15 16 gtk_init(&argc, &argv); 17 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 18 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("控制元件", -1, NULL, NULL, NULL));//设置窗口标题 19 //设置窗口边框宽度30 20 gtk_container_border_width(GTK_CONTAINER(window), 30); 21 //创建垂直框 22 vbox = gtk_vbox_new(FALSE, 0); 23 gtk_container_add(GTK_CONTAINER(window), vbox); 24 25 //新建标签1 26 label1 = gtk_label_new (g_locale_to_utf8("进度条", -1, NULL, NULL, NULL)); 27 //将标签添加到垂直框 28 gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 0); 29 //创建进度条 30 adjustment = gtk_adjustment_new(70.0, 0.0, 100.0, 1.0, 0.0, 0.0); 31 bar = gtk_progress_bar_new_with_adjustment(GTK_ADJUSTMENT(adjustment)); 32 gtk_progress_bar_set_bar_style(GTK_PROGRESS_BAR(bar), GTK_PROGRESS_CONTINUOUS); 33 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(bar), GTK_PROGRESS_LEFT_TO_RIGHT); 34 //将进度条添加到垂直框 35 gtk_box_pack_start(GTK_BOX(vbox), bar, TRUE, TRUE, 15); 36 37 //新建标签2 38 label2 = gtk_label_new (g_locale_to_utf8("微调按钮", -1, NULL, NULL, NULL)); 39 //将标签添加到垂直框 40 gtk_box_pack_start(GTK_BOX(vbox), label2, TRUE, TRUE, 0); 41 //创建微调按钮 42 adjustment = gtk_adjustment_new(80.0, 0.0, 100.0, 1.0, 0.0, 0.0); 43 spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1.0, 1); 44 //将微调按钮添加到垂直框 45 gtk_box_pack_start(GTK_BOX(vbox), spinbutton, TRUE, TRUE, 15); 46 47 //新建标签3 48 label3 = gtk_label_new (g_locale_to_utf8("下拉列表", -1, NULL, NULL, NULL)); 49 //将标签添加到垂直框 50 gtk_box_pack_start(GTK_BOX(vbox), label3, TRUE, TRUE, 0); 51 //创建组合框 52 glist = NULL; 53 glist = g_list_append(glist, "banana"); 54 glist = g_list_append(glist, "apple"); 55 glist = g_list_append(glist, "orange"); 56 glist = g_list_append(glist, "pear"); 57 glist = g_list_append(glist, "strawberry"); 58 combo = gtk_combo_new(); 59 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); 60 //将组合框添加到垂直框 61 gtk_box_pack_start(GTK_BOX(vbox), combo, TRUE, TRUE, 15); 62 gtk_widget_show_all(window); 63 gtk_main(); 64 return 0; 65 66 }
使用GCC编译
gcc -o control_example control_example.c `pkg-config --libs --cflags gtk+-2.0`
./control_example
运行结果为
2单选按钮(radio)、复选按钮(check)
创建单选按钮函数有两个,原型如下:
GtkWidget *gtk_radio_button_new(GSList *group);
GtkWidget *gtk_radio_button_new_with_label(GSlist *group, gchar *label);
创建复选按钮函数也有两个,原型如下:
GtkWidget *gtk_check_button_new(void);
GtkWidget *gtk_check_button_new_with_label( gchar *label);
第一个函数创建无标签按钮,第二个函数用于创建带有文本标签的按钮。
下面给出一个程序例子, check_radio.c
注意:生产第一个radio按钮时,group参数为NULL,而以后每次在该组创建一个radio按钮时都要使用gtk_radio_button_group函数获得新的group值
1 #include<gtk/gtk.h> 2 3 int main(int argc, char *argv[]) 4 { 5 GtkWidget *window; 6 GtkWidget *table; 7 GtkWidget *label1; 8 GtkWidget *label2; 9 GSList *group; 10 GtkWidget *check; 11 GtkWidget *radio; 12 13 gtk_init(&argc, &argv); 14 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 15 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("单选、复选按钮", -1, NULL, NULL, NULL));//设置窗口标题 16 //设置窗口边框宽度15 17 gtk_container_border_width(GTK_CONTAINER(window), 15); 18 //建立表格 19 table = gtk_table_new (4, 4, FALSE); 20 //定义标签 21 label1 = gtk_label_new (g_locale_to_utf8("业余时间活动爱好", -1, NULL, NULL, NULL)); 22 label2 = gtk_label_new (g_locale_to_utf8("平时每天学习时间", -1, NULL, NULL, NULL)); 23 24 //添加表格到窗口 25 gtk_container_add(GTK_CONTAINER (window), table); 26 //将元件分别添加到表格中 27 gtk_table_attach (GTK_TABLE(table), label1, 0, 2, 0, 1, 28 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 0); 29 30 gtk_table_attach (GTK_TABLE(table), label2, 0, 2, 2, 3, 31 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 5); 32 //生成四个check按钮,分别添加到表格中 33 check = gtk_check_button_new_with_label(g_locale_to_utf8("篮球", -1, NULL, NULL, NULL)); 34 gtk_table_attach(GTK_TABLE(table), check, 0, 1, 1, 2, 35 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10); 36 37 check = gtk_check_button_new_with_label(g_locale_to_utf8("足球", -1, NULL, NULL, NULL)); 38 gtk_table_attach(GTK_TABLE(table), check, 1, 2, 1, 2, 39 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10); 40 41 check = gtk_check_button_new_with_label(g_locale_to_utf8("爬山", -1, NULL, NULL, NULL)); 42 gtk_table_attach(GTK_TABLE(table), check, 2, 3, 1, 2, 43 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10); 44 45 check = gtk_check_button_new_with_label(g_locale_to_utf8("郊游", -1, NULL, NULL, NULL)); 46 gtk_table_attach(GTK_TABLE(table), check, 3, 4, 1, 2, 47 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10); 48 49 //生成四个radio按钮,分别添加到表格中,注意:生产第一个radio按钮时,group参数为NULL, 50 //而以后每次在该组创建一个radio按钮时都要使用gtk_radio_button_group函数获得新的group值 51 radio = gtk_radio_button_new_with_label(NULL, g_locale_to_utf8("3~4小时", -1, NULL, NULL, NULL)); 52 gtk_table_attach(GTK_TABLE(table), radio, 0, 1, 3, 4, 53 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 54 55 group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio)); 56 radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8("4~5小时", -1, NULL, NULL, NULL)); 57 gtk_table_attach(GTK_TABLE(table), radio, 1, 2, 3, 4, 58 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 59 60 group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio)); 61 radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8("5~6小时", -1, NULL, NULL, NULL)); 62 gtk_table_attach(GTK_TABLE(table), radio, 2, 3, 3, 4, 63 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 64 65 group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio)); 66 radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8(">=6小时", -1, NULL, NULL, NULL)); 67 gtk_table_attach(GTK_TABLE(table), radio, 3, 4, 3, 4, 68 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5); 69 70 gtk_widget_show_all(window); 71 gtk_main(); 72 return 0; 73 74 75 }
使用GCC编译
gcc -o check_radio check_radio.c `pkg-config --libs --cflags gtk+-2.0`
./check_radio
运行结果为
3下拉菜单
创建菜单的函数有两个,函数原型如下:
GtkWidget *gtk_menu_new();
GtkWidget *gtk_menu_new_with_label(gchar *label);
第一个函数创建无标签菜单,第二个函数用于创建带有文本标签的菜单。
创建菜单项的函数类似于创建菜单,函数原型如下:
GtkWidget *gtk_menu_item_new();
GtkWidget *gtk_menu_item_new_with_label(gchar *label);
插入菜单项的函数原型如下:
void gtk_menu_append (GtkMenu *menu, GtkWidget *child);
void gtk_menu_item_set_submenu (GtkMenuItem item, GtkMenu *menu);
创建菜单条函数原型如下:
GtkWidget *gtk_menu_bar_new(void);
向菜单条中加入菜单
void gtk_menu_bar_append (GtkMenuBar *bar, GtkWidget *child);
创建菜单的步骤如下:
- 使用gtk_menu_new()生成一个新菜单。
- 使用gtk_menu_item_new() 或gtk_menu_item_new_with_label()生成一个新的菜单项,然后使用 gtk_menu_item_append()将每一个菜单项加入到菜单中,使用 gtk_menu_item_new ()或 gtk_menu_item_new_with_label()创建主菜单项。
- 使用 gtk_menu_item_set_submenu ()将各个菜单加入到主菜单项中。
- 使用gtk_menu_bar_new()创建菜单条,这一步仅需做一次。然后使用 gtk_menu_bar_append 把主菜单项加入到菜单条上。
下面是程序例子,menu_example.c
1 #include<gtk/gtk.h> 2 3 int main(int argc, char *argv[]) 4 { 5 GtkWidget *window; 6 GtkWidget *menu; 7 GtkWidget *menubar; 8 GtkWidget *rootmenu; 9 GtkWidget *menuitem; 10 11 gtk_init(&argc, &argv); 12 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 13 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("下拉菜单", -1, NULL, NULL, NULL));//设置窗口标题 14 gtk_widget_set_usize(window, 200, 40); 15 //创建新菜单,然后创建3个菜单项,并把菜单项加入到菜单中 16 17 menu = gtk_menu_new(); 18 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("新建", -1, NULL, NULL, NULL)); 19 gtk_menu_append(GTK_MENU(menu), menuitem); 20 21 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("打开", -1, NULL, NULL, NULL)); 22 gtk_menu_append(GTK_MENU(menu), menuitem); 23 24 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("关闭", -1, NULL, NULL, NULL)); 25 gtk_menu_append(GTK_MENU(menu), menuitem); 26 27 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("保存", -1, NULL, NULL, NULL)); 28 gtk_menu_append(GTK_MENU(menu), menuitem); 29 30 //创建一个主菜单 31 rootmenu = gtk_menu_item_new_with_label(g_locale_to_utf8("文件", -1, NULL, NULL, NULL)); 32 //将菜单加入到主菜单中 33 gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu), menu); 34 35 //创建菜单条 36 menubar = gtk_menu_bar_new(); 37 //将主菜单项加入到菜单条 38 gtk_menu_bar_append(GTK_MENU_BAR(menubar), rootmenu); 39 40 //下面创建第二组菜单 41 menu = gtk_menu_new(); 42 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("复制", -1, NULL, NULL, NULL)); 43 gtk_menu_append(GTK_MENU(menu), menuitem); 44 45 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("剪切", -1, NULL, NULL, NULL)); 46 gtk_menu_append(GTK_MENU(menu), menuitem); 47 48 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("粘贴", -1, NULL, NULL, NULL)); 49 gtk_menu_append(GTK_MENU(menu), menuitem); 50 51 menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("删除", -1, NULL, NULL, NULL)); 52 gtk_menu_append(GTK_MENU(menu), menuitem); 53 54 rootmenu = gtk_menu_item_new_with_label(g_locale_to_utf8("编辑", -1, NULL, NULL, NULL)); 55 //将菜单加入到主菜单中 56 gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu), menu); 57 58 gtk_menu_bar_append(GTK_MENU_BAR(menubar), rootmenu); 59 //将菜单条加入到窗口中 60 gtk_container_add(GTK_CONTAINER(window), menubar); 61 62 gtk_widget_show_all(window); 63 gtk_main(); 64 return 0; 65 66 67 }
使用GCC编译
gcc -o menu_example menu_example.c `pkg-config --libs --cflags gtk+-2.0`
./menu_example
运行结果为
下拉菜单截图工具截不出来。。
信号与回调函数
图形用户界面的程序是事件驱动的程序。程序进入gtk_ain()函数后,等待事件的发生,一旦发生某个事件,相应的信号将产生。如果程序中定义了相应的消息处理函数(也称回调函数),系统将自动进行调用。
1添加信号
信号的作用是对某个元件添加一个用户交互的功能。函数g_signal_connect() 可以把一个信号处理函数(或称回调函数)添加到一个元件上,在元件和消息处理函数间建立关联,该函数原型如下:
gulong g_signal_connect (GtkObject *object, ghar *name,
Gcallback callback_func, gpointer func_data);
参数object是一个元件的指针,指向将产生信号的元件;name表示消息或事件的类型,
一个按钮所有的事件类型与含义如下:
- activate:激活的时候发生
- clicked:单击以后发生
- enter:鼠标指针进入这个按钮以后发生
- leave:鼠标指针离开这个按钮以后发生
- pressed:鼠标按下以后发生
- released:鼠标释放以后发生
参数callback_func表示信号产生后将要执行的回调函数,func_data为传递给回调函数的数据,与callback_func函数的第二个参数相同
在 g_signal_connect函数中,使用事件的不同名称来区分不同的事件(即第二个参数name)。
2回调函数
消息处理函数(回调函数)原型如下:
void callback_func (GtkWidget *widget, gpointer func_data);
参数widget指向要接收消息的元件,参数 func_data指向消息产生时传递给该函数的数据。
程序例子 signal_example.c
1 #include<gtk/gtk.h> 2 3 GtkWidget *window; 4 GtkWidget *table; 5 GtkWidget *button; 6 GtkWidget *label1; 7 GtkWidget *label2; 8 GtkWidget *label3; 9 int i = 0; 10 11 //定义信号回调函数 12 void on_clicked(GtkWidget *widget, gpointer data) 13 { 14 char a[20]; 15 ++i; 16 gcvt((float)i, 3, a); 17 18 gtk_label_set_text(GTK_LABEL(label2), a); 19 } 20 21 int main(int argc, char *argv[]) 22 { 23 24 gtk_init(&argc, &argv); 25 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 26 gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("信号与事件", -1, NULL, NULL, NULL));//设置窗口标题 27 //设置窗口边框 28 gtk_container_border_width(GTK_CONTAINER(window), 5); 29 30 //建立表格 31 table = gtk_table_new (2, 3, FALSE); 32 //定义标签、按钮 33 label1 = gtk_label_new (g_locale_to_utf8("点击按钮第", -1, NULL, NULL, NULL)); 34 label2 = gtk_label_new (g_locale_to_utf8("0", -1, NULL, NULL, NULL)); 35 label3 = gtk_label_new (g_locale_to_utf8("次", -1, NULL, NULL, NULL)); 36 button = gtk_button_new_with_label(g_locale_to_utf8("计数", -1, NULL, NULL, NULL)); 37 38 39 //添加表格到窗口 40 gtk_container_add(GTK_CONTAINER (window), table); 41 42 //将元件分别添加到表格中 43 gtk_table_attach (GTK_TABLE(table), label1, 0, 1, 0, 1, 44 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10); 45 gtk_table_attach (GTK_TABLE(table), label2, 1, 2, 0, 1, 46 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10); 47 gtk_table_attach (GTK_TABLE(table), label3, 2, 3, 0, 1, 48 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10); 49 gtk_table_attach (GTK_TABLE(table), button, 2, 3, 1, 2, 50 (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10); 51 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window); 52 gtk_widget_show_all(window); 53 gtk_main(); 54 return 0; 55 }
使用GCC编译
gcc -o signal_example signal_example.c `pkg-config --libs --cflags gtk+-2.0`
./signal_example
运行结果为
The End!