嵌入式成长轨迹23 【Linux应用编程强化】【Linux下的C编程 下】【Linux GUI编程】
一 GTK+/Gnome开发简介
GTK+是一个用于创建图形用户界面(GUI)的图形库,它在功能上类似微软的MFC,为应用程序提供了一套与平台无关的图形用户接口。GTK+最初用于开发GIMP(General Image Manipulation Program),因而称为GTK(GIMP Toolkit)。
1 第一个GTK+应用程序
GtkWidget *gtk_window_new(GtkWindowType windowtype);
GTK_WINDOW_TOPLEVEL
GTK_WINDOW_DIALOG
GTK_WINDOW_POPUP
void gtk_widget_show(GtkWidget *widget);
void gtk_main(void);
1 /* hello.c */ 2 3 #include<gtk/gtk.h> 4 5 int main(int argc, char **argv[]) 6 7 { 8 9 GtkWidget *window; 10 11 gtk_init(&argc, &argv); 12 13 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 14 15 gtk_widget_show(window); 16 17 gtk_main(); 18 19 return 0; 20 21 }
2 信号连接回调函数
#define gtk_signal_connect(object, name, func, func_data) \
gtk_signal_connect_full((object), (name), (func), 0, (func_data), 0, 0, 0)
gulong gtk_signal_connect_full(GtkObject *object, const gchar *name, GtkSignalFunc func, \
GtkCallbackMarshal unsupported, gpointer data, GtkDestroyNotify destroy_func, \
gint object_signal, gint after);
void callback_func(GtkWidget *widget, gpointer callback_data );
#define gtk_signal_connect_object(object, name, func, slot_object) \
gtk_signal_connect_full ((object), (name), (func), 0, (slot_object), 0, 1, 0)
gulong gtk_signal_connect_full(GtkObject *object, const gchar *name, GtkSignalFunc func, \
GtkCallbackMarshal unsupported, gpointer data, GtkDestroyNotify destroy_func, \
gint object_signal, gint after);
void callback_func( GtkObject *object );
1 /* hello2.c */ 2 3 #include <gtk/gtk.h> 4 5 void hello(GtkWidget *widget, gpointer data ) 6 7 { 8 9 g_print ("Hello World!\n"); 10 11 } 12 13 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 14 15 { 16 17 g_print ("delete event occurred\n"); 18 19 return TUNE; 20 21 } 22 23 void destroy(GtkWidget *widget, gpointer data ) 24 25 { 26 27 gtk_main_quit(); 28 29 } 30 31 int main(int argc, char **argv) 32 33 { 34 35 GtkWidget *window; 36 37 GtkWidget *button; 38 39 gtk_init(&argc, &argv); 40 41 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 42 43 gtk_signal_connect(GTK_OBJECT(window), "delete_event", 44 45 GTK_SIGNAL_FUNC(delete_event), NULL); 46 47 gtk_signal_connect(GTK_OBJECT(window), "destroy", 48 49 GTK_SIGNAL_FUNC(destroy), NULL); 50 51 gtk_container_set_border_width(GTK_CONTAINER (window), 30); 52 53 button = gtk_button_new_with_label("Hello World"); 54 55 gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(hello), NULL); 56 57 gtk_container_add(GTK_CONTAINER(window), button); 58 59 gtk_widget_show(button); 60 61 gtk_widget_show(window); 62 63 gtk_main(); 64 65 return 0; 66 67 }
1 /* table.c */ 2 3 #include <gtk/gtk.h> 4 5 void callback1(GtkWidget *widget, gpointer data ) 6 7 { 8 9 g_print ("Button 1 clicked\n"); 10 11 } 12 13 void callback2(GtkWidget *widget, gpointer data ) 14 15 { 16 17 g_print ("Button 2 clicked\n"); 18 19 } 20 21 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 22 23 { 24 25 g_print ("delete event occurred\n"); 26 27 gtk_main_quit(); 28 29 return FALSE; 30 31 } 32 33 int main(int argc, char **argv) 34 35 { 36 37 GtkWidget *window; 38 39 GtkWidget *table; 40 41 GtkWidget *button; 42 43 gtk_init(&argc, &argv); 44 45 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 46 47 gtk_signal_connect(GTK_OBJECT(window), "delete_event", 48 49 GTK_SIGNAL_FUNC(delete_event), NULL); 50 51 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 52 53 table = gtk_table_new(2, 2, TRUE); 54 55 gtk_container_add (GTK_CONTAINER (window), table); 56 57 button = gtk_button_new_with_label("Button 1"); 58 59 gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(callback1), NULL); 60 61 gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 0, 1); 62 63 gtk_widget_show (button); 64 65 button = gtk_button_new_with_label("Button 2"); 66 67 gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(callback2), NULL); 68 69 gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 0, 1); 70 71 gtk_widget_show (button); 72 73 button = gtk_button_new_with_label("Exit"); 74 75 gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); 76 77 gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2); 78 79 gtk_widget_show (button); 80 81 gtk_widget_show (table); 82 83 gtk_widget_show(window); 84 85 gtk_main(); 86 87 return 0; 88 89 }
二 常用GTK+构件
GTK+中的构件非常丰富,这一节主要介绍其中部分常用的构件,例如按钮、标签、对话框等。下面首先讨论构件的定位。
1 构件定位
在用GTK+构件创建程序界面时,使用容器来实现构件的定位。GTK+中有两种容器,其中一种只能容纳一个子构件,例如GtkWindow;而另外一种则可以容纳多个子构件,例如GtkHBox、GtkVBox以及GtkTable等。
1).GtkWindow构件
GtkWidget* gtk_window_new(GtkWindowType type);
void gtk_window_set_title(GtkWindow *window, const gchar *title);
void gtk_window_set_default_size(GtkWindow *window, gint width, gint height);
2).GtkBox构件
GtkWidget* gtk_hbox_new(gboolean homogeneous, gint spacing);
GtkWidget* gtk_vbox_new(gboolean homogeneous, gint spacing);
void gtk_box_pack_start(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding);
void gtk_box_pack_end(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding);
3).GtkTable构件
GtkWidget *gtk_table_new( guint rows, guint columns, gboolean homogeneous);
void gtk_table_attach(GtkTable *table, GtkWidget *child, guint left_attach, guint right_attach, guint top_attach, guint bottom_attach, GtkAttachOptions xoptions, GtkAttachOptions yoptions, guint xpadding, guint ypadding);
void gtk_table_attach_defaults(GtkTable *table, GtkWidget *widget, guint left_attach, guint right_attach, guint top_attach, guint bottom_attach);
2 按钮构件
1).普通按钮(GtkButton)
GtkWidget* gtk_button_new(void);
GtkWidget* gtk_button_new_with_label(const gchar *label);
2).开关按钮(GtkToggleButton)
GtkWidget *gtk_toggle_button_new(void);
GtkWidget *gtk_toggle_button_new_with_label(const gchar *label);
gboolean gtk_toggle_button_get_active (GtkToggleButton *toggle_button);
3).复选按钮(GtkCheckButton)
GtkWidget *gtk_check_button_new(void);
GtkWidget *gtk_check_button_new_with_label(const gchar *label);
4).单选按钮(GtkRadioButton)
GtkWidget *gtk_radio_button_new(CSList *group);
GtkWidget *gtk_radio_button_new_with_label(CSList *group, gchar *label);
GSList* gtk_radio_button_group(GtkRadioButton *radio_button);
1 /* radio.c */ 2 3 #include <gtk/gtk.h> 4 5 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 6 7 { 8 9 g_print ("delete event occurred\n"); 10 11 gtk_main_quit(); 12 13 return FALSE; 14 15 } 16 17 int main(int argc, char **argv) /* 主函数 */ 18 19 { 20 21 GtkWidget *window; 22 23 GtkWidget *vbox; 24 25 GtkWidget *button; 26 27 GSList *group; 28 29 gtk_init(&argc, &argv); /* 初始化 */ 30 31 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建主窗口 */ 32 33 /* 为delete_event事件连接一个回调函数 */ 34 35 gtk_signal_connect(GTK_OBJECT(window), "delete_event", 36 37 GTK_SIGNAL_FUNC(delete_event), NULL); 38 39 gtk_window_set_title(GTK_WINDOW (window), "radio"); /* 设置窗口的标题 */ 40 41 gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 设置窗口的边框宽度 */ 42 43 /* 创建一个垂直组装盒 */ 44 45 vbox = gtk_vbox_new(FALSE, 0); 46 47 gtk_container_add(GTK_CONTAINER(window), vbox); /* 添加到主窗口之中 */ 48 49 gtk_widget_show(vbox); 50 51 /* 创建第一个单选按钮 */ 52 53 button = gtk_radio_button_new_with_label(NULL, "radio button 1"); 54 55 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); /* 将按钮添加到组装盒之中 */ 56 57 gtk_widget_show(button); 58 59 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); /* 创建按钮组 */ 60 61 /* 创建第二个单选按钮 */ 62 63 button = gtk_radio_button_new_with_label(group, "radio button 2"); 64 65 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); 66 67 gtk_widget_show(button); 68 69 /* 创建第三个单选按钮 */ 70 71 button = gtk_radio_button_new_with_label(group, "radio button 3"); 72 73 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); 74 75 gtk_widget_show(button); 76 77 /* 显示主窗口 */ 78 79 gtk_widget_show(window); 80 81 /* 事件循环 */ 82 83 gtk_main(); 84 85 return 0; 86 87 }
3 标签构件
标签(GtkLabel)也是应用程序中经常使用的一种构件。
GtkWidget *gtk_label_new(const char *str );
gchar *gtk_label_get_text(GtkLabel *label);
void gtk_label_set_text(GtkLabel *label, const char *str);
void gtk_label_set_justify(GtkLabel *label, GtkJustification jtype);
GTK_JUSTIFY_LEFT:左对齐
GTK_JUSTIFY_RIGHT:右对齐
GTK_JUSTIFY_CENTER:居中对齐(默认)
GTK_JUSTIFY_FILL:填满
1 /* labels.c */ 2 3 #include <gtk/gtk.h> 4 5 int main(int argc, char **argv) 6 7 { 8 9 GtkWidget *window; 10 11 GtkWidget *vbox; 12 13 GtkWidget *label; 14 15 gtk_init(&argc, &argv); /* 初始化 */ 16 17 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建主窗口 */ 18 19 gtk_signal_connect(GTK_OBJECT(window), "destroy", 20 21 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 22 23 gtk_window_set_title(GTK_WINDOW (window), "label"); /* 设置窗口的标题 */ 24 25 gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 设置窗口的边框宽度 */ 26 27 /* 创建一个垂直组装盒 */ 28 29 vbox = gtk_vbox_new(FALSE, 0); 30 31 gtk_container_add(GTK_CONTAINER(window), vbox); /* 添加到主窗口之中 */ 32 33 /* 创建第一个标签 */ 34 35 label = gtk_label_new("Line 1: Hello\nLine 2 : World"); 36 37 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 38 39 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); 40 41 /* 创建第二个标签 */ 42 43 label = gtk_label_new("Line 3 : Linux\nLine 4 : Programming "); 44 45 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); 46 47 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); 48 49 /* 显示所有构件 */ 50 51 gtk_widget_show_all(window); 52 53 /* 事件循环 */ 54 55 gtk_main(); 56 57 return 0; 58 59 }
4 文本及文本输入构件
文本构件和文本输入构件是两个比较常用的构件,用于显示和编辑文本。
1).文本构件
2).文本输入构件
1 /* text.c */ 2 3 #include <gtk/gtk.h> 4 5 void editable_toggle(GtkWidget *widget, GtkWidget *text) /* 复选框回调函数 */ 6 7 { 8 9 gtk_editable_set_editable(GTK_EDITABLE(text), 10 11 GTK_TOGGLE_BUTTON(widget)->active); 12 13 } 14 15 16 17 gint delete_event(GtkWidget *widget, /* 退出按钮回调函数 */ 18 19 GdkEvent *event, gpointer data) 20 21 { 22 23 gtk_main_quit(); 24 25 return FALSE; 26 27 } 28 29 30 31 int main(int argc, char **argv) /* 主函数 */ 32 33 { 34 35 GtkWidget *window; 36 37 GtkWidget *vbox, *hbox; 38 39 GtkWidget *text; 40 41 GtkWidget *check; 42 43 GtkWidget *button; 44 45 gtk_init(&argc, &argv); /* 初始化 */ 46 47 /* 创建主窗口 */ 48 49 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 50 51 gtk_signal_connect(GTK_OBJECT(window), "destroy", 52 53 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 54 55 gtk_window_set_title(GTK_WINDOW (window), "text"); 56 57 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 58 59 /* 创建一个垂直组装盒 */ 60 61 vbox = gtk_vbox_new(FALSE, 0); 62 63 gtk_container_add(GTK_CONTAINER(window), vbox); 64 65 /* 创建一个文本构件 */ 66 67 text = gtk_text_new(NULL, NULL); 68 69 gtk_text_insert(text, NULL, NULL, /* 插入文本使用系统默认字体和颜色*/ 70 71 NULL, "Source Code :", -1); 72 73 gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0); 74 75 /* 创建一个水平组装盒 */ 76 77 hbox = gtk_hbox_new(FALSE, 0); 78 79 gtk_container_add(GTK_CONTAINER(vbox), hbox); 80 81 /* 创建一个复选按钮 */ 82 83 check = gtk_check_button_new_with_label("Editable"); 84 85 gtk_signal_connect(GTK_OBJECT(check), "toggled", 86 87 GTK_SIGNAL_FUNC(editable_toggle), text); 88 89 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); 90 91 gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); 92 93 /* 创建退出按钮 */ 94 95 button = gtk_button_new_with_label("Exit"); 96 97 gtk_signal_connect(GTK_OBJECT(button), "clicked", 98 99 G_CALLBACK(delete_event), NULL); 100 101 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 102 103 /* 显示所有构件 */ 104 105 gtk_widget_show_all(window); 106 107 /* 事件循环 */ 108 109 gtk_main(); 110 111 return 0; 112 113 }
1 /* entry.c */ 2 3 #include <gtk/gtk.h> 4 5 void enter_callback(GtkWidget *widget, gpointer data) /* 回调函数 */ 6 7 { 8 9 const gchar *entry_text; 10 11 entry_text = gtk_entry_get_text(GTK_ENTRY(widget)); 12 13 printf("Entry contents : %s\n", entry_text); 14 15 } 16 17 void editable_toggle(GtkWidget *widget, GtkWidget *entry) 18 19 { 20 21 gtk_editable_set_editable(GTK_EDITABLE(entry), GTK_TOGGLE_BUTTON(widget)->active); 22 23 } 24 25 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) 26 27 { 28 29 gtk_main_quit(); 30 31 return FALSE; 32 33 } 34 35 int main(int argc, char **argv) /* 主函数 */ 36 37 { 38 39 GtkWidget *window; 40 41 GtkWidget *vbox, *hbox; 42 43 GtkWidget *entry; 44 45 GtkWidget *check; 46 47 GtkWidget *button; 48 49 gtk_init(&argc, &argv); /* 初始化 */ 50 51 /* 创建主窗口 */ 52 53 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 54 55 gtk_signal_connect(GTK_OBJECT(window), "destroy", 56 57 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 58 59 gtk_window_set_title(GTK_WINDOW (window), "label"); 60 61 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 62 63 /* 创建一个垂直组装盒 */ 64 65 vbox = gtk_vbox_new(FALSE, 0); 66 67 gtk_container_add(GTK_CONTAINER(window), vbox); 68 69 /* 创建一个文本输入构件 */ 70 71 entry = gtk_entry_new(); 72 73 gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(enter_callback), NULL); 74 75 gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0); 76 77 /* 创建一个水平组装盒 */ 78 79 hbox = gtk_hbox_new(FALSE, 0); 80 81 gtk_container_add(GTK_CONTAINER(vbox), hbox); 82 83 /* 创建一个复选按钮 */ 84 85 check = gtk_check_button_new_with_label("Editable"); 86 87 gtk_signal_connect(GTK_OBJECT(check), "toggled", GTK_SIGNAL_FUNC(editable_toggle), entry); 88 89 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); 90 91 gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); 92 93 /* 创建Exit按钮 */ 94 95 button = gtk_button_new_with_label("Exit"); 96 97 gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); 98 99 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 100 101 /* 显示所有构件 */ 102 103 gtk_widget_show_all(window); 104 105 /* 事件循环 */ 106 107 gtk_main(); 108 109 return 0; 110 111 }
5 进度条构件
进度条构件(GtkProgressBar)一般用来显示应用程序中某个操作的状态。
1 /* progressbar.c */ 2 3 #include <gtk/gtk.h> 4 5 gint started; /* 状态标志 */ 6 7 gint paused; 8 9 gint progress(gpointer data ) /* 更新进度条 */ 10 11 { 12 13 gfloat i; 14 15 GtkAdjustment *adj; /* 调整对象 */ 16 17 i = gtk_progress_get_value(GTK_PROGRESS(data)); /* 获取进度条的当前值 */ 18 19 if(0 == started) /* 判断进度更新是否被停止 */ 20 21 { 22 23 if(0 == paused) /* 判断进度更新是否被暂停 */ 24 25 { 26 27 i = i + 1; 28 29 paused = 0; 30 31 } 32 33 } 34 35 else 36 37 { 38 39 i = 100; 40 41 } 42 43 adj = GTK_PROGRESS (data)->adjustment; 44 45 if (i > adj->upper) /* 判断是否超出取值范围 */ 46 47 { 48 49 i = adj->lower; 50 51 } 52 53 gtk_progress_set_value(GTK_PROGRESS (data), i); /* 更新进度条 */ 54 55 return (TRUE ) ; 56 57 } 58 59 60 61 void show_toggle(GtkWidget *widget, GtkWidget *pbar) /* 显示文本复选框回调函数 */ 62 63 { 64 65 gtk_progress_set_show_text(GTK_PROGRESS(pbar), 66 67 GTK_TOGGLE_BUTTON(widget)->active); 68 69 } 70 71 72 73 gint start_event(GtkWidget *widget, gpointer data) /* 开始按钮回调函数 */ 74 75 { 76 77 gfloat i; 78 79 i = gtk_progress_get_value(GTK_PROGRESS(pbar)); /* 获取进度条的当前值 */ 80 81 if(100 == i) 82 83 { 84 85 started = 0; /* 设置状态标志*/ 86 87 paused = 0; 88 89 } 90 91 return TRUE; 92 93 } 94 95 96 97 gint pause_event(GtkWidget *widget, gpointer data) /* 暂停按钮回调函数 */ 98 99 { 100 101 if(0 == paused) /* 判断是否已经暂停 */ 102 103 { 104 105 paused = 1; 106 107 } 108 109 else /* 如果已经暂停,则取消暂停 */ 110 111 { 112 113 paused = 0; 114 115 } 116 117 return TRUE; 118 119 } 120 121 122 123 gint stop_event(GtkWidget *widget, gpointer data) /* 停止按钮回调函数 */ 124 125 { 126 127 started = 1; /* 设置状态标志*/ 128 129 paused = 1; 130 131 return TRUE; 132 133 } 134 135 136 137 gint delete_event(GtkWidget *widget, /* 关闭按钮回调函数 */ 138 139 GdkEvent *event, gpointer data) 140 141 { 142 143 gtk_main_quit(); 144 145 return FALSE; 146 147 } 148 149 150 151 int main(int argc, char **argv) /* 主函数 */ 152 153 { 154 155 GtkWidget *window; 156 157 GtkWidget *vbox, *hbox; 158 159 GtkWidget *pbar; 160 161 GtkWidget *check; 162 163 GtkWidget *button; 164 165 166 167 gtk_init(&argc, &argv); /* 初始化 */ 168 169 /* 创建主窗口 */ 170 171 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 172 173 gtk_signal_connect(GTK_OBJECT(window), "destroy", 174 175 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 176 177 gtk_window_set_title(GTK_WINDOW (window), "progressbar"); 178 179 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 180 181 /* 创建一个垂直组装盒 */ 182 183 vbox = gtk_vbox_new(FALSE, 0); 184 185 gtk_container_add(GTK_CONTAINER(window), vbox); 186 187 /* 创建进度条构件 */ 188 189 pbar = gtk_progress_bar_new(); 190 191 gtk_progress_bar_set_bar_style( /* 设置进度条构件更新方式 */ 192 193 GTK_PROGRESS_BAR(pbar), GTK_PROGRESS_CONTINUOUS); 194 195 gtk_progress_set_format_string( /* 如果显示文本,指定其格式 */ 196 197 GTK_PROGRESS(pbar), "%p"); 198 199 gtk_timeout_add (100, progress, pbar); /* 对进度条进行连续更新,间隔时间为0.1s */ 200 201 gtk_box_pack_start(GTK_BOX(vbox), pbar, TRUE, TRUE, 0); 202 203 /* 创建一个水平组装盒 */ 204 205 hbox = gtk_hbox_new(FALSE, 0); 206 207 gtk_container_add(GTK_CONTAINER(vbox), hbox); 208 209 /* 创建显示文本复选按钮 */ 210 211 check = gtk_check_button_new_with_label("Show Text"); 212 213 gtk_signal_connect(GTK_OBJECT(check), "toggled", 214 215 GTK_SIGNAL_FUNC(show_toggle), pbar); 216 217 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); 218 219 gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); 220 221 /* 创建一个水平组装盒 */ 222 223 hbox = gtk_hbox_new(FALSE, 0); 224 225 gtk_container_add(GTK_CONTAINER(vbox), hbox); 226 227 /* 创建开始按钮 */ 228 229 button = gtk_button_new_with_label("start"); 230 231 gtk_signal_connect(GTK_OBJECT(button), "clicked", 232 233 G_CALLBACK(start_event), pbar); 234 235 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 236 237 /* 创建暂停按钮 */ 238 239 button = gtk_button_new_with_label("Pause"); 240 241 gtk_signal_connect(GTK_OBJECT(button), "clicked", 242 243 G_CALLBACK(pause_event), NULL); 244 245 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 246 247 /* 创建停止按钮 */ 248 249 button = gtk_button_new_with_label("Stop"); 250 251 gtk_signal_connect(GTK_OBJECT(button), "clicked", 252 253 G_CALLBACK(stop_event), NULL); 254 255 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 256 257 /* 创建关闭按钮 */ 258 259 button = gtk_button_new_with_label("Close"); 260 261 gtk_signal_connect(GTK_OBJECT(button), "clicked", 262 263 G_CALLBACK(delete_event), NULL); 264 265 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); 266 267 /* 显示所有构件 */ 268 269 gtk_widget_show_all(window); 270 271 /* 事件循环 */ 272 273 gtk_main(); 274 275 return 0; 276 277 }
6 组合框
组合框构件(GtkCombo)在应用程序中经常用到,它包含一个文本输入框和一个下拉列表,用户可以在下拉列表中进行选择,也可以在文本框中直接输入文本。
1 /* combo.c */ 2 3 #include <gtk/gtk.h> 4 5 #define N 16 6 7 typedef struct _Calculate /* 定义结构体,用来向回调函数传递参数 */ 8 9 { 10 11 GtkWidget *entry1; 12 13 GtkWidget *entry2; 14 15 GtkWidget *combo; 16 17 GtkWidget *label; 18 19 } Calculate; 20 21 22 23 gint cal_event(GtkWidget *widget, Calculate *cal) /* 计算按钮回调函数 */ 24 25 { 26 27 const gchar *text1, *text2; 28 29 const char *options; 30 31 gchar result[N]; 32 33 char operator; 34 35 gint x, y, z; 36 37 gint flag; 38 39 text1 = gtk_entry_get_text( /* 获取文本输入构件中的字符串 */ 40 41 GTK_ENTRY(cal->entry1)); 42 43 x = atoi(text1); /* 将得到的字符串转换为整数 */ 44 45 text2 = gtk_entry_get_text( /* 获取文本输入构件中的字符串 */ 46 47 GTK_ENTRY(cal->entry2)); 48 49 y = atoi(text2); /* 将得到的字符串转换为整数 */ 50 51 options = gtk_entry_get_text( /* 获取组合框构件中用户选择的字符串 */ 52 53 GTK_ENTRY(GTK_COMBO(cal->combo)->entry)); 54 55 operator = *options; /* 提取运算符 */ 56 57 flag = 0; /* 出错标志,用于后面的错误检测 */ 58 59 switch (operator) /* 对两个操作数进行运算 */ 60 61 { 62 63 case '+': /* 加法运算 */ 64 65 z = x + y; 66 67 break; 68 69 case '-': /* 减法运算 */ 70 71 z = x - y; 72 73 break; 74 75 case 'x': /* 乘法运算 */ 76 77 z = x * y; 78 79 break; 80 81 case '/': /* 除法运算 */ 82 83 if(0 == y) /* 除数为0时,设置出错标志 */ 84 85 flag = 1; 86 87 else 88 89 z = x / y; 90 91 break; 92 93 case '%': /* 取余运算 */ 94 95 if(0 == y) /* 除数为0时,设置出错标志 */ 96 97 flag = 1; 98 99 else 100 101 z = x % y; 102 103 break; 104 105 default: /* 其余情况,设置出错标志 */ 106 107 flag = 1; 108 109 } 110 111 if(1 == flag) /* 检测出错标志 */ 112 113 g_sprintf(result, "error"); 114 115 else 116 117 g_sprintf(result, "%d", z); /* 将运算结果转换为字符串 */ 118 119 gtk_label_set_text(GTK_LABEL(cal->label), result); /* 输出运算结果或出错提示 */ 120 121 return TRUE; 122 123 } 124 125 126 127 gint close_event(GtkWidget *widget, /* 关闭按钮回调函数 */ 128 129 GdkEvent *event, gpointer data) 130 131 { 132 133 gtk_main_quit(); 134 135 return TRUE; 136 137 } 138 139 140 141 int main(int argc, char **argv) /* 主函数 */ 142 143 { 144 145 Calculate *cal; 146 147 GtkWidget *window; 148 149 GtkWidget *table; 150 151 GtkWidget *label; 152 153 GtkWidget *button; 154 155 156 157 gtk_init(&argc, &argv); /* 初始化 */ 158 159 /* 创建主窗口 */ 160 161 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 162 163 gtk_signal_connect(GTK_OBJECT(window), "destroy", 164 165 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 166 167 gtk_window_set_title(GTK_WINDOW (window), "combo"); 168 169 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 170 171 /* 创建一个6x2的网格 */ 172 173 table = gtk_table_new(6, 2, TRUE); 174 175 gtk_container_add( /* 将网格添加到主窗口之中 */ 176 177 GTK_CONTAINER (window), table); 178 179 /* 创建一个文本输入构件,用于操作数输入 */ 180 181 cal->entry1 = gtk_entry_new(); 182 183 gtk_table_attach_defaults( /* 将文本输入构件放到网格之中 */ 184 185 GTK_TABLE (table), cal->entry1, 0, 2, 0, 1); 186 187 /* 创建一个组合框构件,用于操作符选择 */ 188 189 cal->combo = gtk_combo_new(); 190 191 GList *glist=NULL; /* 定义Glist链表 */ 192 193 glist = g_list_append(glist, "+"); /* 向Glist链表中追加字符串 */ 194 195 glist = g_list_append(glist, "-"); 196 197 glist = g_list_append(glist, "x"); 198 199 glist = g_list_append(glist, "/"); 200 201 glist = g_list_append(glist, "%"); 202 203 gtk_combo_set_popdown_strings( /* 设置下拉列表中选项 */ 204 205 GTK_COMBO(cal->combo), glist); 206 207 gtk_entry_set_text(GTK_ENTRY( /* 文本输入框中显示文本 */ 208 209 GTK_COMBO(cal->combo)->entry), "operator"); 210 211 gtk_table_attach_defaults ( /* 将组合框构件放到网格之中 */ 212 213 GTK_TABLE (table), cal->combo, 0, 2, 1, 2); 214 215 /* 创建一个文本输入构件,用于操作数输入 */ 216 217 cal->entry2 = gtk_entry_new(); 218 219 gtk_table_attach_defaults ( /* 将文本输入构件放到网格之中 */ 220 221 GTK_TABLE (table),cal->entry2, 0, 2, 2, 3); 222 223 /* 创建计算按钮 */ 224 225 button = gtk_button_new_with_label("Calulate"); 226 227 gtk_signal_connect(GTK_OBJECT(button), "clicked", 228 229 G_CALLBACK(cal_event), cal); 230 231 gtk_table_attach_defaults ( /* 将按钮构件放到网格之中 */ 232 233 GTK_TABLE (table), button, 0, 2, 3, 4); 234 235 /* 创建一个标签构件 */ 236 237 label = gtk_label_new("Result : "); 238 239 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); 240 241 gtk_table_attach_defaults ( /* 将标签构件放到网格之中 */ 242 243 GTK_TABLE (table), label, 0, 1, 4, 5); 244 245 /* 创建一个标签构件,用于计算结果显示 */ 246 247 cal->label = gtk_label_new(" "); 248 249 gtk_label_set_justify(GTK_LABEL(cal->label), GTK_JUSTIFY_CENTER); 250 251 gtk_table_attach_defaults ( /* 将标签构件放到网格之中 */ 252 253 GTK_TABLE (table), cal->label, 1, 2, 4, 5); 254 255 /* 创建关闭按钮 */ 256 257 button = gtk_button_new_with_label("Close"); 258 259 gtk_signal_connect(GTK_OBJECT(button), "clicked", 260 261 G_CALLBACK(close_event), NULL); 262 263 gtk_table_attach_defaults ( /* 将按钮构件放到网格之中 */ 264 265 GTK_TABLE (table), button, 1, 2, 5, 6); 266 267 /* 显示所有构件 */ 268 269 gtk_widget_show_all(window); 270 271 /* 事件循环 */ 272 273 gtk_main(); 274 275 return 0; 276 277 }
7 对话框
对话框(GtkDialog)主要用来弹出消息,或完成一些类似任务
1 /* dialog.c */ 2 3 #include <gtk/gtk.h> 4 5 #define N 64 6 7 gint yes_callback(GtkWidget *widget, gpointer data) /* yes按钮回调函数 */ 8 9 { 10 11 gtk_main_quit(); 12 13 return TRUE; 14 15 } 16 17 18 19 gint no_callback(GtkWidget *widget, gpointer data) /* no按钮回调函数 */ 20 21 { 22 23 gchar text[N]; 24 25 static gint i; /* 纪录按钮按下的次数 */ 26 27 i++; 28 29 g_sprintf(text, "\"No\" button clicked %d times.", i); 30 31 gtk_label_set_text(GTK_LABEL(data), text); /* 设置标签构件显示的文本 */ 32 33 return TRUE; 34 35 } 36 37 38 39 int main(int argc, char **argv) /* 主函数 */ 40 41 { 42 43 GtkWidget *window; 44 45 GtkWidget *label; 46 47 GtkWidget *button; 48 49 gtk_init(&argc, &argv); /* 初始化 */ 50 51 /* 创建对话框 */ 52 53 window = gtk_dialog_new(); 54 55 /* 创建并添加标签构件 */ 56 57 label = gtk_label_new("\nDo you want to exit?\n"); 58 59 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); 60 61 gtk_box_pack_start( /* 添加到对话框上方的垂直组装盒中 */ 62 63 GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE, TRUE, 0); 64 65 /* 创建并添加标签构件 */ 66 67 label = gtk_label_new(" "); 68 69 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); 70 71 gtk_box_pack_start( /* 添加到对话框上方的垂直组装盒中 */ 72 73 GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE, TRUE, 0); 74 75 /* 创建并添加按钮构件 */ 76 77 button = gtk_button_new_with_label("Yes"); 78 79 gtk_signal_connect( /* 设置回调函数 */ 80 81 GTK_OBJECT(button), "clicked", G_CALLBACK(yes_callback), NULL); 82 83 gtk_box_pack_start( /* 添加到对话框下方的活动区域中 */ 84 85 GTK_BOX(GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); 86 87 /* 创建并添加按钮构件 */ 88 89 button = gtk_button_new_with_label("No"); 90 91 gtk_signal_connect( /* 设置回调函数 */ 92 93 GTK_OBJECT(button), "clicked", G_CALLBACK(no_callback), label); 94 95 gtk_box_pack_start( /* 添加到对话框下方的活动区域中 */ 96 97 GTK_BOX(GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); 98 99 /* 显示所有构件 */ 100 101 gtk_widget_show_all(window); 102 103 /* 事件循环 */ 104 105 gtk_main(); 106 107 return 0; 108 109 }
1 /* aboutdialog.c */ 2 3 #include <gtk/gtk.h> 4 5 #include <libgnomeui/gnome-about.h> /* 注意包含该头文件 */ 6 7 #define N 64 8 9 10 11 gint about_callback(GtkWidget *widget, gpointer data) /* 关于按钮回调函数 */ 12 13 { 14 15 GtkWidget *about; 16 17 const gchar *authors[] = { /* 软件作者信息 */ 18 19 "Xxxxxx Xxx <xxxxxx@kernel.org>", 20 21 "Xxxxxx Xxx <xxxxxx@gnome.org>", 22 23 "Xxxxxx Xxx <xxxxxx@gnome.org>", 24 25 NULL 26 27 }; 28 29 const gchar *documenters[] = { /* 文档作者信息 */ 30 31 "Xxxxxx Xxx <xxxxxx@gnome.org>", 32 33 NULL 34 35 }; 36 37 about = gnome_about_new ("XXXX", "1.00", /* 创建Gnome关于对话框 */ 38 39 "(C) 2009 the Free Software Foundation", 40 41 "comments ... ", 42 43 authors, 44 45 documenters, 46 47 NULL, 48 49 NULL) ; 50 51 gtk_widget_show(about); /* 显示Gnome关于对话框 */ 52 53 return TRUE; 54 55 } 56 57 58 59 gint close_callback(GtkWidget *widget, gpointer data) /* 关闭按钮回调函数 */ 60 61 { 62 63 gtk_main_quit(); 64 65 return TRUE; 66 67 } 68 69 70 71 int main(int argc, char **argv) /* 主函数 */ 72 73 { 74 75 GtkWidget *window; 76 77 GtkWidget *vbox; 78 79 GtkWidget *button; 80 81 82 83 gtk_init(&argc, &argv); /* 初始化 */ 84 85 /* 创建主窗口 */ 86 87 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 88 89 gtk_signal_connect(GTK_OBJECT(window), "destroy", 90 91 GTK_SIGNAL_FUNC(gtk_main_quit), NULL); 92 93 gtk_window_set_title(GTK_WINDOW (window), "combo"); 94 95 gtk_container_set_border_width(GTK_CONTAINER (window), 15); 96 97 /* 创建一个垂直组装盒 */ 98 99 vbox = gtk_vbox_new(FALSE, 0); 100 101 gtk_container_add(GTK_CONTAINER(window), vbox); 102 103 /* 创建关于按钮 */ 104 105 button = gtk_button_new_with_label("About"); 106 107 gtk_signal_connect(GTK_OBJECT(button), "clicked", 108 109 G_CALLBACK(about_callback), NULL); 110 111 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); 112 113 /* 创建关闭按钮 */ 114 115 button = gtk_button_new_with_label("Close"); 116 117 gtk_signal_connect(GTK_OBJECT(button), "clicked", 118 119 G_CALLBACK(close_callback), NULL); 120 121 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); 122 123 /* 显示所有构件 */ 124 125 gtk_widget_show_all(window); 126 127 /* 事件循环 */ 128 129 gtk_main(); 130 131 return 0; 132 133 }
三 GUI生成器Glade
Glade是针对GTK+/Gnome快速图形界面开发的应用软件,它类似于Microsoft Windows环境下的VB、VC++以及Delphi等。Glade的可视化编程可以使程序员的主要精力集中于应用程序核心功能的开发上,而不需为界面的修改重复编写大量烦琐的Gtk+函数。
1 打开Glade
Linux系统启动图形界面之后,在终端上输入glade或在桌面上单击【Application】|【Programming】|【Glade Interface Designer】命令,即可启动Glade。一般能看到3个窗口:工程管理窗口、常用构件窗口和属性管理窗口。
2 创建应用程序界面
在创建应用程序界面之前,首先新建一个工程项目。单击工程管理窗口上方的【New】按钮,会弹出新建Project对话框。
1).创建一个新的窗口
2).在窗口中添加各种构件
3).为构件的信号连接回调函数
4).生成创建应用程序界面的源代码
3 编译连接程序
Glade中使用Automake工具,可以根据编译选项自动生成Makefile文件。
四 常见面试题
常见面试题1:简述编写GTK+应用程序的一般步骤。
常见面试题2:Glade的可视化编程与Microsoft Windows环境下的VB、VC++以及Delphi等工具有何差异?
五 小结
在Linux系统中,基于GTK+构件的应用程序图形界面,执行效率高,占用资源少,有着很好的发展前景。这一章主要介绍了GTK+编程的基本知识,通过本章的学习,读者应该能够编写基本的图形界面应用程序。由于篇幅有限,这里只介绍了很少一部分GTK+构件。