嵌入式成长轨迹23 【Linux应用编程强化】【Linux下的C编程 下】【Linux GUI编程】
2012-04-09 17:58
561 查看
一 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);
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 );
二 常用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);
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:填满
4 文本及文本输入构件
文本构件和文本输入构件是两个比较常用的构件,用于显示和编辑文本。
1).文本构件
2).文本输入构件
5 进度条构件
进度条构件(GtkProgressBar)一般用来显示应用程序中某个操作的状态。
6 组合框
组合框构件(GtkCombo)在应用程序中经常用到,它包含一个文本输入框和一个下拉列表,用户可以在下拉列表中进行选择,也可以在文本框中直接输入文本。
7 对话框
对话框(GtkDialog)主要用来弹出消息,或完成一些类似任务
三 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+构件。
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);
/* hello.c */ #include<gtk/gtk.h> int main(int argc, char **argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_show(window); gtk_main(); return 0; }
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 );
/* hello2.c */ #include <gtk/gtk.h> void hello(GtkWidget *widget, gpointer data ) { g_print ("Hello World!\n"); } gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { g_print ("delete event occurred\n"); return TUNE; } void destroy(GtkWidget *widget, gpointer data ) { gtk_main_quit(); } int main(int argc, char **argv) { GtkWidget *window; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL); gtk_container_set_border_width(GTK_CONTAINER (window), 30); button = gtk_button_new_with_label("Hello World"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(hello), NULL); gtk_container_add(GTK_CONTAINER(window), button); gtk_widget_show(button); gtk_widget_show(window); gtk_main(); return 0; }
/* table.c */ #include <gtk/gtk.h> void callback1(GtkWidget *widget, gpointer data ) { g_print ("Button 1 clicked\n"); } void callback2(GtkWidget *widget, gpointer data ) { g_print ("Button 2 clicked\n"); } gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { g_print ("delete event occurred\n"); gtk_main_quit(); return FALSE; } int main(int argc, char **argv) { GtkWidget *window; GtkWidget *table; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); gtk_container_set_border_width(GTK_CONTAINER (window), 15); table = gtk_table_new(2, 2, TRUE); gtk_container_add (GTK_CONTAINER (window), table); button = gtk_button_new_with_label("Button 1"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(callback1), NULL); gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 0, 1); gtk_widget_show (button); button = gtk_button_new_with_label("Button 2"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(callback2), NULL); gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 0, 1); gtk_widget_show (button); button = gtk_button_new_with_label("Exit"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2); gtk_widget_show (button); gtk_widget_show (table); gtk_widget_show(window); gtk_main(); return 0; }
二 常用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);
/* radio.c */ #include <gtk/gtk.h> gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { g_print ("delete event occurred\n"); gtk_main_quit(); return FALSE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *vbox; GtkWidget *button; GSList *group; gtk_init(&argc, &argv); /* 初始化 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建主窗口 */ /* 为delete_event事件连接一个回调函数 */ gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); gtk_window_set_title(GTK_WINDOW (window), "radio"); /* 设置窗口的标题 */ gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 设置窗口的边框宽度 */ /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 添加到主窗口之中 */ gtk_widget_show(vbox); /* 创建第一个单选按钮 */ button = gtk_radio_button_new_with_label(NULL, "radio button 1"); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); /* 将按钮添加到组装盒之中 */ gtk_widget_show(button); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); /* 创建按钮组 */ /* 创建第二个单选按钮 */ button = gtk_radio_button_new_with_label(group, "radio button 2"); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); gtk_widget_show(button); /* 创建第三个单选按钮 */ button = gtk_radio_button_new_with_label(group, "radio button 3"); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); gtk_widget_show(button); /* 显示主窗口 */ gtk_widget_show(window); /* 事件循环 */ gtk_main(); return 0; }
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:填满
/* labels.c */ #include <gtk/gtk.h> int main(int argc, char **argv) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; gtk_init(&argc, &argv); /* 初始化 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建主窗口 */ gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "label"); /* 设置窗口的标题 */ gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 设置窗口的边框宽度 */ /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 添加到主窗口之中 */ /* 创建第一个标签 */ label = gtk_label_new("Line 1: Hello\nLine 2 : World"); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); /* 创建第二个标签 */ label = gtk_label_new("Line 3 : Linux\nLine 4 : Programming "); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
4 文本及文本输入构件
文本构件和文本输入构件是两个比较常用的构件,用于显示和编辑文本。
1).文本构件
2).文本输入构件
/* text.c */ #include <gtk/gtk.h> void editable_toggle(GtkWidget *widget, GtkWidget *text) /* 复选框回调函数 */ { gtk_editable_set_editable(GTK_EDITABLE(text), GTK_TOGGLE_BUTTON(widget)->active); } gint delete_event(GtkWidget *widget, /* 退出按钮回调函数 */ GdkEvent *event, gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *vbox, *hbox; GtkWidget *text; GtkWidget *check; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建主窗口 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "text"); gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 创建一个文本构件 */ text = gtk_text_new(NULL, NULL); gtk_text_insert(text, NULL, NULL, /* 插入文本使用系统默认字体和颜色*/ NULL, "Source Code :", -1); gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0); /* 创建一个水平组装盒 */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(vbox), hbox); /* 创建一个复选按钮 */ check = gtk_check_button_new_with_label("Editable"); gtk_signal_connect(GTK_OBJECT(check), "toggled", GTK_SIGNAL_FUNC(editable_toggle), text); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); /* 创建退出按钮 */ button = gtk_button_new_with_label("Exit"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
/* entry.c */ #include <gtk/gtk.h> void enter_callback(GtkWidget *widget, gpointer data) /* 回调函数 */ { const gchar *entry_text; entry_text = gtk_entry_get_text(GTK_ENTRY(widget)); printf("Entry contents : %s\n", entry_text); } void editable_toggle(GtkWidget *widget, GtkWidget *entry) { gtk_editable_set_editable(GTK_EDITABLE(entry), GTK_TOGGLE_BUTTON(widget)->active); } gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *vbox, *hbox; GtkWidget *entry; GtkWidget *check; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建主窗口 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "label"); gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 创建一个文本输入构件 */ entry = gtk_entry_new(); gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(enter_callback), NULL); gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0); /* 创建一个水平组装盒 */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(vbox), hbox); /* 创建一个复选按钮 */ check = gtk_check_button_new_with_label("Editable"); gtk_signal_connect(GTK_OBJECT(check), "toggled", GTK_SIGNAL_FUNC(editable_toggle), entry); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); /* 创建Exit按钮 */ button = gtk_button_new_with_label("Exit"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
5 进度条构件
进度条构件(GtkProgressBar)一般用来显示应用程序中某个操作的状态。
/* progressbar.c */ #include <gtk/gtk.h> gint started; /* 状态标志 */ gint paused; gint progress(gpointer data ) /* 更新进度条 */ { gfloat i; GtkAdjustment *adj; /* 调整对象 */ i = gtk_progress_get_value(GTK_PROGRESS(data)); /* 获取进度条的当前值 */ if(0 == started) /* 判断进度更新是否被停止 */ { if(0 == paused) /* 判断进度更新是否被暂停 */ { i = i + 1; paused = 0; } } else { i = 100; } adj = GTK_PROGRESS (data)->adjustment; if (i > adj->upper) /* 判断是否超出取值范围 */ { i = adj->lower; } gtk_progress_set_value(GTK_PROGRESS (data), i); /* 更新进度条 */ return (TRUE ) ; } void show_toggle(GtkWidget *widget, GtkWidget *pbar) /* 显示文本复选框回调函数 */ { gtk_progress_set_show_text(GTK_PROGRESS(pbar), GTK_TOGGLE_BUTTON(widget)->active); } gint start_event(GtkWidget *widget, gpointer data) /* 开始按钮回调函数 */ { gfloat i; i = gtk_progress_get_value(GTK_PROGRESS(pbar)); /* 获取进度条的当前值 */ if(100 == i) { started = 0; /* 设置状态标志*/ paused = 0; } return TRUE; } gint pause_event(GtkWidget *widget, gpointer data) /* 暂停按钮回调函数 */ { if(0 == paused) /* 判断是否已经暂停 */ { paused = 1; } else /* 如果已经暂停,则取消暂停 */ { paused = 0; } return TRUE; } gint stop_event(GtkWidget *widget, gpointer data) /* 停止按钮回调函数 */ { started = 1; /* 设置状态标志*/ paused = 1; return TRUE; } gint delete_event(GtkWidget *widget, /* 关闭按钮回调函数 */ GdkEvent *event, gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *vbox, *hbox; GtkWidget *pbar; GtkWidget *check; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建主窗口 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "progressbar"); gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 创建进度条构件 */ pbar = gtk_progress_bar_new(); gtk_progress_bar_set_bar_style( /* 设置进度条构件更新方式 */ GTK_PROGRESS_BAR(pbar), GTK_PROGRESS_CONTINUOUS); gtk_progress_set_format_string( /* 如果显示文本,指定其格式 */ GTK_PROGRESS(pbar), "%p"); gtk_timeout_add (100, progress, pbar); /* 对进度条进行连续更新,间隔时间为0.1s */ gtk_box_pack_start(GTK_BOX(vbox), pbar, TRUE, TRUE, 0); /* 创建一个水平组装盒 */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(vbox), hbox); /* 创建显示文本复选按钮 */ check = gtk_check_button_new_with_label("Show Text"); gtk_signal_connect(GTK_OBJECT(check), "toggled", GTK_SIGNAL_FUNC(show_toggle), pbar); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); gtk_box_pack_start(GTK_BOX(hbox), check, TRUE, TRUE, 0); /* 创建一个水平组装盒 */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(vbox), hbox); /* 创建开始按钮 */ button = gtk_button_new_with_label("start"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(start_event), pbar); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 创建暂停按钮 */ button = gtk_button_new_with_label("Pause"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(pause_event), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 创建停止按钮 */ button = gtk_button_new_with_label("Stop"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(stop_event), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 创建关闭按钮 */ button = gtk_button_new_with_label("Close"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(delete_event), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
6 组合框
组合框构件(GtkCombo)在应用程序中经常用到,它包含一个文本输入框和一个下拉列表,用户可以在下拉列表中进行选择,也可以在文本框中直接输入文本。
/* combo.c */ #include <gtk/gtk.h> #define N 16 typedef struct _Calculate /* 定义结构体,用来向回调函数传递参数 */ { GtkWidget *entry1; GtkWidget *entry2; GtkWidget *combo; GtkWidget *label; } Calculate; gint cal_event(GtkWidget *widget, Calculate *cal) /* 计算按钮回调函数 */ { const gchar *text1, *text2; const char *options; gchar result ; char operator; gint x, y, z; gint flag; text1 = gtk_entry_get_text( /* 获取文本输入构件中的字符串 */ GTK_ENTRY(cal->entry1)); x = atoi(text1); /* 将得到的字符串转换为整数 */ text2 = gtk_entry_get_text( /* 获取文本输入构件中的字符串 */ GTK_ENTRY(cal->entry2)); y = atoi(text2); /* 将得到的字符串转换为整数 */ options = gtk_entry_get_text( /* 获取组合框构件中用户选择的字符串 */ GTK_ENTRY(GTK_COMBO(cal->combo)->entry)); operator = *options; /* 提取运算符 */ flag = 0; /* 出错标志,用于后面的错误检测 */ switch (operator) /* 对两个操作数进行运算 */ { case '+': /* 加法运算 */ z = x + y; break; case '-': /* 减法运算 */ z = x - y; break; case 'x': /* 乘法运算 */ z = x * y; break; case '/': /* 除法运算 */ if(0 == y) /* 除数为0时,设置出错标志 */ flag = 1; else z = x / y; break; case '%': /* 取余运算 */ if(0 == y) /* 除数为0时,设置出错标志 */ flag = 1; else z = x % y; break; default: /* 其余情况,设置出错标志 */ flag = 1; } if(1 == flag) /* 检测出错标志 */ g_sprintf(result, "error"); else g_sprintf(result, "%d", z); /* 将运算结果转换为字符串 */ gtk_label_set_text(GTK_LABEL(cal->label), result); /* 输出运算结果或出错提示 */ return TRUE; } gint close_event(GtkWidget *widget, /* 关闭按钮回调函数 */ GdkEvent *event, gpointer data) { gtk_main_quit(); return TRUE; } int main(int argc, char **argv) /* 主函数 */ { Calculate *cal; GtkWidget *window; GtkWidget *table; GtkWidget *label; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建主窗口 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "combo"); gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 创建一个6x2的网格 */ table = gtk_table_new(6, 2, TRUE); gtk_container_add( /* 将网格添加到主窗口之中 */ GTK_CONTAINER (window), table); /* 创建一个文本输入构件,用于操作数输入 */ cal->entry1 = gtk_entry_new(); gtk_table_attach_defaults( /* 将文本输入构件放到网格之中 */ GTK_TABLE (table), cal->entry1, 0, 2, 0, 1); /* 创建一个组合框构件,用于操作符选择 */ cal->combo = gtk_combo_new(); GList *glist=NULL; /* 定义Glist链表 */ glist = g_list_append(glist, "+"); /* 向Glist链表中追加字符串 */ glist = g_list_append(glist, "-"); glist = g_list_append(glist, "x"); glist = g_list_append(glist, "/"); glist = g_list_append(glist, "%"); gtk_combo_set_popdown_strings( /* 设置下拉列表中选项 */ GTK_COMBO(cal->combo), glist); gtk_entry_set_text(GTK_ENTRY( /* 文本输入框中显示文本 */ GTK_COMBO(cal->combo)->entry), "operator"); gtk_table_attach_defaults ( /* 将组合框构件放到网格之中 */ GTK_TABLE (table), cal->combo, 0, 2, 1, 2); /* 创建一个文本输入构件,用于操作数输入 */ cal->entry2 = gtk_entry_new(); gtk_table_attach_defaults ( /* 将文本输入构件放到网格之中 */ GTK_TABLE (table),cal->entry2, 0, 2, 2, 3); /* 创建计算按钮 */ button = gtk_button_new_with_label("Calulate"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(cal_event), cal); gtk_table_attach_defaults ( /* 将按钮构件放到网格之中 */ GTK_TABLE (table), button, 0, 2, 3, 4); /* 创建一个标签构件 */ label = gtk_label_new("Result : "); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_table_attach_defaults ( /* 将标签构件放到网格之中 */ GTK_TABLE (table), label, 0, 1, 4, 5); /* 创建一个标签构件,用于计算结果显示 */ cal->label = gtk_label_new(" "); gtk_label_set_justify(GTK_LABEL(cal->label), GTK_JUSTIFY_CENTER); gtk_table_attach_defaults ( /* 将标签构件放到网格之中 */ GTK_TABLE (table), cal->label, 1, 2, 4, 5); /* 创建关闭按钮 */ button = gtk_button_new_with_label("Close"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(close_event), NULL); gtk_table_attach_defaults ( /* 将按钮构件放到网格之中 */ GTK_TABLE (table), button, 1, 2, 5, 6); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
7 对话框
对话框(GtkDialog)主要用来弹出消息,或完成一些类似任务
/* dialog.c */ #include <gtk/gtk.h> #define N 64 gint yes_callback(GtkWidget *widget, gpointer data) /* yes按钮回调函数 */ { gtk_main_quit(); return TRUE; } gint no_callback(GtkWidget *widget, gpointer data) /* no按钮回调函数 */ { gchar text ; static gint i; /* 纪录按钮按下的次数 */ i++; g_sprintf(text, "\"No\" button clicked %d times.", i); gtk_label_set_text(GTK_LABEL(data), text); /* 设置标签构件显示的文本 */ return TRUE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *label; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建对话框 */ window = gtk_dialog_new(); /* 创建并添加标签构件 */ label = gtk_label_new("\nDo you want to exit?\n"); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_box_pack_start( /* 添加到对话框上方的垂直组装盒中 */ GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE, TRUE, 0); /* 创建并添加标签构件 */ label = gtk_label_new(" "); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); gtk_box_pack_start( /* 添加到对话框上方的垂直组装盒中 */ GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE, TRUE, 0); /* 创建并添加按钮构件 */ button = gtk_button_new_with_label("Yes"); gtk_signal_connect( /* 设置回调函数 */ GTK_OBJECT(button), "clicked", G_CALLBACK(yes_callback), NULL); gtk_box_pack_start( /* 添加到对话框下方的活动区域中 */ GTK_BOX(GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); /* 创建并添加按钮构件 */ button = gtk_button_new_with_label("No"); gtk_signal_connect( /* 设置回调函数 */ GTK_OBJECT(button), "clicked", G_CALLBACK(no_callback), label); gtk_box_pack_start( /* 添加到对话框下方的活动区域中 */ GTK_BOX(GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
/* aboutdialog.c */ #include <gtk/gtk.h> #include <libgnomeui/gnome-about.h> /* 注意包含该头文件 */ #define N 64 gint about_callback(GtkWidget *widget, gpointer data) /* 关于按钮回调函数 */ { GtkWidget *about; const gchar *authors[] = { /* 软件作者信息 */ "Xxxxxx Xxx <xxxxxx@kernel.org>", "Xxxxxx Xxx <xxxxxx@gnome.org>", "Xxxxxx Xxx <xxxxxx@gnome.org>", NULL }; const gchar *documenters[] = { /* 文档作者信息 */ "Xxxxxx Xxx <xxxxxx@gnome.org>", NULL }; about = gnome_about_new ("XXXX", "1.00", /* 创建Gnome关于对话框 */ "(C) 2009 the Free Software Foundation", "comments ... ", authors, documenters, NULL, NULL) ; gtk_widget_show(about); /* 显示Gnome关于对话框 */ return TRUE; } gint close_callback(GtkWidget *widget, gpointer data) /* 关闭按钮回调函数 */ { gtk_main_quit(); return TRUE; } int main(int argc, char **argv) /* 主函数 */ { GtkWidget *window; GtkWidget *vbox; GtkWidget *button; gtk_init(&argc, &argv); /* 初始化 */ /* 创建主窗口 */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_window_set_title(GTK_WINDOW (window), "combo"); gtk_container_set_border_width(GTK_CONTAINER (window), 15); /* 创建一个垂直组装盒 */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* 创建关于按钮 */ button = gtk_button_new_with_label("About"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(about_callback), NULL); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); /* 创建关闭按钮 */ button = gtk_button_new_with_label("Close"); gtk_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(close_callback), NULL); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); /* 显示所有构件 */ gtk_widget_show_all(window); /* 事件循环 */ gtk_main(); return 0; }
三 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+构件。
相关文章推荐
- 嵌入式成长轨迹20 【Linux应用编程强化】【Linux下的C编程 下】【进程间通信】
- 嵌入式成长轨迹18 【Linux应用编程强化】【Linux下的C编程 下】【标准输入输出】
- 嵌入式成长轨迹21 【Linux应用编程强化】【Linux下的C编程 下】【多线程编程】
- 嵌入式成长轨迹22 【Linux应用编程强化】【Linux下的C编程 下】【网络编程】
- 嵌入式成长轨迹19 【Linux应用编程强化】【Linux下的C编程 下】【进程操作】
- 嵌入式成长轨迹24【Linux应用编程强化】【Linux下的C编程 下】【实例:Linux命令实现】
- 嵌入式成长轨迹25 【Linux应用编程强化】【Linux下的C编程 下】【实例:客户端/服务器端程序】
- 嵌入式成长轨迹17 【Linux应用编程强化】【Linux下的C编程 下】【文件系统编程】
- 嵌入式成长轨迹26 【Linux应用编程强化】【中嵌第二阶段】【Linux网络应用】
- 嵌入式成长轨迹27 【Linux应用编程强化】【中嵌第二阶段】【进程管理】
- 嵌入式成长轨迹16 【Linux应用编程强化阶段】【Linux下的C编程下】【Linux c基本应用】
- 嵌入式成长轨迹28 【Linux应用编程强化】【中嵌第二阶段】【linux串口应用开发】
- 嵌入式成长轨迹14 【嵌入式环境及基础】【Linux下的C编程 上】【gcc、gdb和GNU Make】
- 基于GTK+和X-window的GUI在嵌入式Linux中的应用
- 【嵌入式Linux学习七步曲之第七篇 Linux的高级应用编程】进程间的通信机制
- 嵌入式linux面试题解析(三)——Linux应用编程部分一
- 嵌入式成长轨迹1 【嵌入式环境及基础】【嵌入式Linux软件开发入门】【linux基础命令】
- 【嵌入式Linux学习七步曲之第七篇 Linux的高级应用编程】网络编程中并发服务器的设计模式
- 嵌入式成长轨迹3 【嵌入式环境及基础】【嵌入式Linux软件开发入门】【VI编辑器的使用】
- 嵌入式成长轨迹32【嵌入式学习阶段】【ARM环境调试】【Linux Ubuntu其它环境调试】