GTK3.0 使用CSS设置控件背景色

最后更新于:2022-04-01 20:22:21

[我已参加2014“博客之星的”评选,觉得我的文章对您有帮助的,请投上您宝贵的一票](http://vote.blog.csdn.net/blogstar2014/details?username=jsh13417#content) GTK 2.0 在windows运行下,会出现文本框无法输入的问题。这个查找了很多资料,说是2.0版本的问题,目前还未找到好的解决方法。但是使用GTK3.0没有影响。而GTK3.0在设置控件背景图片没有找到合适的方法。参考网上给的例子使用CSS来实现(详细参见参考资料内容)。但是在window下运行并未生效。具体原因不明: ~~~ /* Compile with: gcc -Wall -o backimage `pkg-config --cflags --libs gtk+-3.0` backimage.c */ #include int main(int argc, char *argv[]) { GtkWidget *window; /*----- CSS ----------- */ GtkCssProvider *provider; GdkDisplay *display; GdkScreen *screen; /*-----------------------*/ gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* gtk_window_set_default_size (GTK_WINDOW(window), 500, 300); */ g_signal_connect (GTK_WIDGET(window), "destroy", G_CALLBACK (gtk_main_quit), NULL); /*------------- CSS --------------------------------------------------------------------------------------------------*/ provider = gtk_css_provider_new (); display = gdk_display_get_default (); screen = gdk_display_get_default_screen (display); gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER); gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), " GtkWindow {\n" " background-image: url('abstract-blue-02.jpg');\n" "}\n", -1, NULL); g_object_unref (provider); /*----------------------------------------------------------------------------------------------------------------------*/ gtk_widget_show_all (window); gtk_main (); return(0); } ~~~ GTK3.0 Ubuntu系统下安装命令如下: apt-get install gtk3.0 参考资料: [http://www.gtkforums.com/viewtopic.php?f=3&t=988&sid=b63d18d182917efd7e2b04eb8c5e50c1&start=15](http://www.gtkforums.com/viewtopic.php?f=3&t=988&sid=b63d18d182917efd7e2b04eb8c5e50c1&start=15) windows 应用程序添加ICON https://mail.gnome.org/archives/gtk-app-devel-list/2005-November/msg00169.html
';

链表和树型存储结构

最后更新于:2022-04-01 20:22:19

### 树型和链表存储类型结构的不同,今天也是看例子学会了如何使用相关函数。先看下效果吧! ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779a4ede5.jpg) ~~~ /*File:tree.c *Auth:sjin *Date:2014-03-23 *Mail:413977243@qq.com */ #include enum{ ID_COLUMN, TOGGLE_COLUMN, TEXT_COLUMN, N_COLUMN }; typedef struct _listitem ListItem; struct _listitem{ gint id; gboolean toggle; const gchar *text; }; ListItem t[5] = { {1,TRUE,"小明"}, {2,FALSE,"大宝"}, {3,TRUE,"测试用名称"}, {4,FALSE,"显示的文本"}, {5,TRUE,"是可编辑的"} }; GtkListStore * create_list_model(void) { GtkListStore *list_store; GtkTreeIter iter; gint i; /*创建一个存储,行数和对应的数据类型列表*/ list_store = gtk_list_store_new(N_COLUMN,G_TYPE_INT,G_TYPE_BOOLEAN,G_TYPE_STRING); for(i = 0;i < 5;i++){ /*向LIST_trore添加一个新行 * iter将指向这个新行,这个函数调用后事空的 * 需要gtk_list_store_set()函数来填写数值 * */ gtk_list_store_append(list_store,&iter); gtk_list_store_set(list_store,&iter,ID_COLUMN,t[i].id, TOGGLE_COLUMN,t[i].toggle, TEXT_COLUMN,t[i].text, -1); } return list_store; } GtkWidget* create_list(GtkListStore* list_store) { GtkWidget* view; GtkTreeModel* model; GtkCellRenderer* renderer; GtkTreeViewColumn* column; model = GTK_TREE_MODEL(list_store); /*创建一个模型初始化model的控件*/ view = gtk_tree_view_new_with_model(model); /*创建一个文本单元绘制器*/ renderer = gtk_cell_renderer_text_new(); /*创建一个视图列表*/ column = gtk_tree_view_column_new_with_attributes("数字",renderer,"text",ID_COLUMN,NULL); /*附加一列列表*/ gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); /*创建一个开关单元绘制器*/ renderer = gtk_cell_renderer_toggle_new(); /*设置控件属性*/ g_object_set(G_OBJECT(renderer),"activatable",TRUE,NULL); /*设置开关单元绘制器为:当为TURE时为单元按钮,为FAULE时为多选按钮*/ gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(renderer),TRUE); /**/ column = gtk_tree_view_column_new_with_attributes("按钮",renderer,"active",TOGGLE_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer),"editable",TRUE,NULL); column = gtk_tree_view_column_new_with_attributes("文本",renderer,"text",TEXT_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); return view; } void show_list(void) { GtkWidget* window; GtkWidget* frame; GtkWidget* view; GtkListStore* model; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),window); gtk_window_set_title(GTK_WINDOW(window),"TREEVIEW --使用 LISTSTORE"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window),10); frame = gtk_frame_new("可编辑的列表"); gtk_frame_set_label_align(GTK_FRAME(frame),1.0,0); gtk_container_add(GTK_CONTAINER(window),frame); /*创建一个存储列表*/ model = create_list_model(); /*创建单元格列表*/ view = create_list(model); gtk_container_add(GTK_CONTAINER(frame),view); gtk_widget_show_all(window); } enum { XCLASS_COLUMN, LEADER_COLUMN, STUDENTS_COLUMN, GIRLS_COLUMN }; typedef struct _treeitem TreeItem; struct _treeitem{ const char* xclass; const char* leader; gint students; gint girls; }; TreeItem ti[3] = { {"一年级一班","李晓",40,20}, {"一年级二班","张红",44,18}, {"一年级三班","刘丽",42,20} }; TreeItem tj[3] = { {"二年级一班","王可",34,16}, {"二年级二班","赵倩",34,18}, {"二年级三班","犹可",38,20} }; GtkTreeStore* create_tree_model(void) { GtkTreeStore* treestore; GtkTreeIter iter,parent; gint i; /*创建树型存储结构,每行都有一种存储类型*/ treestore = gtk_tree_store_new(4,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_INT,G_TYPE_INT); /*向树型存储结构添加新行 *iter 指向新行的空间 * */ gtk_tree_store_append(treestore,&iter,NULL); gtk_tree_store_set(treestore,&iter,0,"一年级",-1); gtk_tree_store_append(treestore,&iter,NULL); gtk_tree_store_set(treestore,&iter,0,"二年级",-1); /*gboolean gtk_tree_model_get_iter_from_string(GtkTreeModel *treestore, * GtkTreeIter *iter, * const gchar *path_string); * 参数:treestore :存储树形列表 * iter : 指向存储结构 * path_string : 路径 * 返回值:TRUE : iter 不为空 * FAule: 为空 * */ if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(treestore),&parent,"0")){ for(i = 0; i < 3; i++){ gtk_tree_store_append(treestore,&iter,&parent); gtk_tree_store_set(treestore,&iter, XCLASS_COLUMN,ti[i].xclass, LEADER_COLUMN,ti[i].leader, STUDENTS_COLUMN,ti[i].students, GIRLS_COLUMN,ti[i].girls, -1); } } if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(treestore),&parent,"1")){ for(i = 0; i < 3; i++) { gtk_tree_store_append(treestore,&iter,&parent); gtk_tree_store_set(treestore,&iter, XCLASS_COLUMN,tj[i].xclass, LEADER_COLUMN,tj[i].leader, STUDENTS_COLUMN,tj[i].students, GIRLS_COLUMN,tj[i].girls, -1); } } return treestore; } GtkWidget* create_tree(GtkTreeStore* treestore) { GtkWidget* view; GtkCellRenderer* renderer; GtkTreeViewColumn* column; /*创建树型显示模型*/ view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(treestore)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("班级名",renderer,"text",XCLASS_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("班主任",renderer,"text",LEADER_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("学生总数",renderer,"text",STUDENTS_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("女生总数",renderer,"text",GIRLS_COLUMN,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view),column); return view; } void show_tree(void) { GtkWidget* window; GtkWidget* frame; GtkWidget* view; GtkTreeStore* model; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_widget_destroy),window); gtk_window_set_title(GTK_WINDOW(window),"TREEVIEW----使用TreeStore"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window),10); frame = gtk_frame_new("树型列表"); gtk_container_add(GTK_CONTAINER(window),frame); model = create_tree_model(); view = create_tree(model); gtk_container_add(GTK_CONTAINER(frame),view); gtk_widget_show_all(window); } int main(int argc,char* argv[]) { GtkWidget* window; GtkWidget* vbox; GtkWidget* button; /*初始化*/ gtk_init(&argc,&argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"TREE_VIEW控件"); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); button = gtk_button_new_with_label("创建列表显示"); gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(show_list),NULL); button = gtk_button_new_with_label("创建树型显示"); gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(show_tree),NULL); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ ### 关于GTK学习的例子不是特别的多。这个函数更多相关的例子请给链接。非常感谢!
';

菜单选项

最后更新于:2022-04-01 20:22:16

### 菜单控件 创建菜单栏和子菜单时要用到三种构件: • 一个菜单项(menu item),就是用户要选择的东西,比如,"Save" • 一个菜单(menu),作为菜单项的容器。 • 一个菜单栏(menubar),是各个单独菜单的容器。 ### 下面是创建菜单控件的一般步骤: ### • 用 gtk_menu_new() 创建一个新的菜单 • 多次调用 gtk_menu_item_new() 创建每个你想在你的菜单上出现的菜单项。并使用 gtk_menu_append() 将每个新的菜单项放到 菜单上。 • 用 gtk_menu_item_new() 创建一个菜单项。这将是菜单的根(root),上面显示的文本将自己出现在菜单栏上。 • 用 gtk_menu_item_set_submenu() 将菜单绑定到根菜单项(就是上一步创建的那个)。 • 用 gtk_menu_bar_new 创建一个新的菜单栏。在一个菜单栏上创建一系列菜单时这步只要做一次就行了。 • 用 gtk_menu_bar_append() 将根菜单项放到菜单栏上。 创建一个弹出菜单和上面的几乎是一样,只是在设置回调函数时,如下: ~~~ g_signal_connect_swapped (G_OBJECT (widget), "event", G_CALLBACK (handler), G_OBJECT (menu)); ~~~ 其中widget是你要绑定到的构件,handler是处理函数,而menu是一个用 gtk_menu_new() 创建的菜单。它可以是一个也被菜单栏弹出的菜单。 ### 看下面具体的例子: ### ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779a35f97.jpg) ~~~ /*File:menu_item.c *Date:2013-11-23 *Author:sjin *Mail:413977243@qq.com */ #include #include static void menuitem_response(gchar *string) { printf("%s\n",string); } static int button_press(GtkWidget *widget,GdkEvent *event) { if(event->type == GDK_BUTTON_PRESS){ GdkEventButton *bevent = (GdkEventButton *)event; gtk_menu_popup(GTK_MENU(widget),NULL,NULL,NULL,NULL,bevent->button,bevent->time); /*告诉调用代码我们已经处理这个事件,*/ return TRUE; } /*else 未处理*/ return FALSE; } gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) { /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 * 返回 TRUE,你不希望关闭窗口。 * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/ return FALSE; } /* 另一个回调函数 */ void destroy( GtkWidget *widget,gpointer data ) { gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *menu; GtkWidget *menu_bar; GtkWidget *root_menu; GtkWidget *menu_items; GtkWidget *vbox; GtkWidget *button; char buf[128]; int i; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* 在这里我们连接 "destroy" 事件到一个信号处理函数。 * 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值 * 都会触发这个事件。*/ g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); /* 设置窗口边框的宽度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /*创建窗口宽度*/ gtk_widget_set_size_request(GTK_WIDGET(window),200,100); /************* * 初始化菜单构件 * 记住这里永远不要用gtk_widget_show()函数来显示菜单控件 * 这个是包含菜单项的菜单,运行程序时点击会弹出来 ************/ menu = gtk_menu_new(); /*********×××××××××× * * * ***********/ for(i = 0; i < 3; i++){ /*将名称复制到buf*/ sprintf(buf,"undetmenu-%d",i); /*创建一个菜单项*/ menu_items = gtk_menu_item_new_with_label(buf); /*将它添加到菜单*/ gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_items); /*当菜单被选中时的回调函数*/ g_signal_connect_swapped(G_OBJECT(menu_items),"activate",G_CALLBACK(menuitem_response),g_strdup(buf)); /*显示构件*/ gtk_widget_show(menu_items); } /***************** *这个是根菜单,将成为现实在菜单栏上的标签 *这里不会附上信号处理函数,因为它只是在被按下时弹出的其余的菜单 *****************/ root_menu = gtk_menu_item_new_with_label("根菜单"); gtk_widget_show(root_menu); /************** *指定想要穿件的menu成为根菜单 ***************/ gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),menu); /*将一个菜单和一个按钮放到纵向盒子里面*/ vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); gtk_widget_show(vbox); /**************** *创建一个菜单栏,并添加到主窗口 * ***************/ menu_bar = gtk_menu_bar_new(); gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,FALSE,2); gtk_widget_show(menu_bar); button = gtk_button_new_with_label("点击"); g_signal_connect_swapped(G_OBJECT(button),"event",G_CALLBACK(button_press),menu); gtk_box_pack_end(GTK_BOX(vbox),button,TRUE,TRUE,2); gtk_widget_show(button); /************** *最后把惨淡想添加到菜单栏上 * ***************/ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu); gtk_widget_show(window); gtk_main (); return 0; } ~~~ ### 下面是利用gtk_item_factory来实现菜单选项: ~~~ /***************** *使用套件生成菜单方式 *gtk_item_factory ************/ /*File:menu_item2.c *Date:2014-03-23 *Author:sjin *Mail:413977243@qq.com */ #include #include /*必要的回调函数*/ static void print_hello(GtkWidget *w,gpointer data) { g_message("Hello,World!\n"); } /******************** * 这是用来生成新惨淡的GtkItemFactoryEntry结构 * 第一项 菜单路径 下划线后字母指出惨淡打开的快捷键 * 第二项:这个条目的快捷键 * 第三项:回调函数 * 第四项,回调动作 * 第五项:项类型用 * NULL -> "Item" * "" "Item" * "" 标题 * "<Item>" 创建一个简单的项 * "<CheckItem>" 创建一个检查项 * "<ToggleItem>" 创建一个开关项 * "<RadioItem>" 创建一个选择项 * <path> 选择项链接到的路径 * "<Separator>" 分割线 * "Branch" 创建一个包含子项的项 * "LastBranch" 创建一个右对齐的分支 *******************/ static GtkItemFactoryEntry menu_items[] = { {"/_File", NULL, NULL,0,"<Branch>"}, {"/File/_New", "<control>N", print_hello,0,NULL}, {"/File/_Open", "<control>O", print_hello,0,NULL}, {"/File/_Save", "<control>S" ,print_hello,0,NULL}, {"/File/Save _As", NULL,NULL,0,NULL}, {"/File/sepl", NULL,NULL,0,"<Separator>"}, {"/File/Quit", "<control>Q", gtk_main_quit,0,NULL}, {"/_Options", NULL,NULL,0,"<Branch>"}, {"/Options/Test", NULL,NULL,0,NULL}, {"/_Help", NULL,NULL,0,"<LastBranch>"}, {"/Help/About", NULL,NULL,0,NULL}, }; void get_main_menu(GtkWidget *window,GtkWidget **menu_bar) { GtkItemFactory *item_factory; GtkAccelGroup *accel_group; gint nmenu_items = sizeof(menu_items)/sizeof(menu_items[0]); accel_group = gtk_accel_group_new(); /************** *这个函数初始化套件 *参数1:菜单类型- *参数2:菜单路径 *参数3:指向一个gtk_accel_group 的指针 * ***************/ item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group); /*生成菜单项,把数组里想的数量,数组自身,和菜单项的任意 * 回调函数以此传递给套件*/ gtk_item_factory_create_items(item_factory,nmenu_items,menu_items,NULL); /*把新的加速组绑定到窗口*/ gtk_window_add_accel_group(GTK_WINDOW(window),accel_group); if(menu_bar){ /*返回套件已经创建的菜单栏*/ *menu_bar = gtk_item_factory_get_widget(item_factory,"<main>"); } } gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) { /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 * 返回 TRUE,你不希望关闭窗口。 * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/ return TRUE; } /* 另一个回调函数 */ void destroy( GtkWidget *widget,gpointer data ) { gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *menu_bar; GtkWidget *vbox; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* 在这里我们连接 "destroy" 事件到一个信号处理函数。 * 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值 * 都会触发这个事件。*/ g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); /* 设置窗口边框的宽度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /*创建窗口宽度*/ gtk_widget_set_size_request(GTK_WIDGET(window),200,100); vbox = gtk_vbox_new(FALSE,1); gtk_container_add(GTK_CONTAINER(window),vbox); gtk_widget_show(vbox); get_main_menu(window,&menu_bar); gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,TRUE,0); gtk_widget_show(menu_bar); gtk_widget_show(window); gtk_main (); return 0; } ~~~ 问题:在运行后无法将菜单栏显示出来的的问题? 运行程序需要ROOT权限。具体原因不清楚。。 </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="笔记本控件、">笔记本控件、<a class="anchorjs-link " href="#笔记本控件、" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:14</span></p> <div id="md-view"> ### 笔记本构件(The NoteBook Widget) 笔记本构件(The NoteBook Widget)是互相重叠的页面集合,每一页都包含不同的信息,且一次只有一个页面是可见的。该构件在GUI(图形用户接口)编程中很常用。要显示大量的相似信息,同时把它们分别显示时,使用这种构件是一个很好的方法。具体看下面的代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779a1c305.jpg) 具体代码如下: ~~~ /*File:notebook.c *Date:2014-0309 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <stdio.h> /*这个函数旋转页标签的位置*/ void rotate_book(GtkButton *button,GtkNotebook *notebook) { gtk_notebook_set_tab_pos(notebook,(notebook->tab_pos + 1) % 4); } /*隐藏或显示页标签和边框*/ void tabsborder_book(GtkButton *button,GtkNotebook *notebook) { gint tval = FALSE; gint bval = FALSE; if(notebook->show_tabs == 0){ tval = TRUE; } if(notebook->show_border == 0){ bval = TRUE; } /*显示或者隐藏页标签*/ gtk_notebook_set_show_tabs(notebook,tval); /*显示或者隐藏边框*/ gtk_notebook_set_show_border(notebook,bval); } /*从笔记本构件上删除页面*/ void remove_book(GtkButton *button,GtkNotebook *notebook) { gint page; page = gtk_notebook_get_current_page(notebook); gtk_notebook_remove_page(notebook,page); /*********** * 必须刷新构件-----这会迫使构件重绘自身*/ gtk_widget_draw(GTK_WIDGET(notebook),NULL); } void delete(GtkWidget *widget,GtkWidget *event,gpointer data) { gtk_main_quit(); } int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *table; GtkWidget *notebook; GtkWidget *frame; GtkWidget *label; GtkWidget *checkbutton; int i; char bufferf[32]; char bufferl[32]; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(delete),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),"notebook 练习"); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); /*表组装,创建表*/ table = gtk_table_new(3,6,FALSE); gtk_container_add(GTK_CONTAINER(window),table); /*创建一个笔记本构件,将标签页放在顶部*/ notebook = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook),GTK_POS_TOP); gtk_table_attach_defaults(GTK_TABLE(table),notebook,0,6,0,1); gtk_widget_show(notebook); /*向笔记本构件中插入标签页*/ for(i = 0; i < 5; i++){ sprintf(bufferf,"笔记本构件框架 %d",i + 1); sprintf(bufferl,"标签页 %d",i + 1); frame = gtk_frame_new(bufferf); gtk_container_set_border_width(GTK_CONTAINER(frame),10); gtk_widget_set_usize(frame,100,75); gtk_widget_show(frame); label = gtk_label_new(bufferf); gtk_container_add(GTK_CONTAINER(frame),label); gtk_widget_show(label); label = gtk_label_new(bufferl); gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook),frame,label); } /*设置起始页为第四页*/ gtk_notebook_set_page(GTK_NOTEBOOK(notebook),3); /*创建一排按钮*/ /*关闭*/ button = gtk_button_new_with_label("关闭"); gtk_signal_connect_object(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(delete),NULL); gtk_table_attach_defaults(GTK_TABLE(table),button,0,1,1,2); gtk_widget_show(button); /*下一页*/ button = gtk_button_new_with_label("下一页"); gtk_signal_connect_object(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_notebook_next_page),GTK_NOTEBOOK(notebook)); gtk_table_attach_defaults(GTK_TABLE(table),button,1,2,1,2); gtk_widget_show(button); /*上一页*/ button = gtk_button_new_with_label("上一页"); gtk_signal_connect_object(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_notebook_prev_page),GTK_NOTEBOOK(notebook)); gtk_table_attach_defaults(GTK_TABLE(table),button,2,3,1,2); gtk_widget_show(button); /*标签页位置*/ button = gtk_button_new_with_label("标签页位置"); gtk_signal_connect(GTK_OBJECT(button),"clicked",(GtkSignalFunc)rotate_book,GTK_NOTEBOOK(notebook)); gtk_table_attach_defaults(GTK_TABLE(table),button,3,4,1,2); gtk_widget_show(button); /*隐藏页标签和边框*/ button = gtk_button_new_with_label("页标签和边框ON、OFF"); gtk_signal_connect(GTK_OBJECT(button),"clicked",(GtkSignalFunc)tabsborder_book,GTK_NOTEBOOK(notebook)); gtk_table_attach_defaults(GTK_TABLE(table),button,4,5,1,2); gtk_widget_show(button); /*删除*/ button = gtk_button_new_with_label("删除"); gtk_signal_connect(GTK_OBJECT(button),"clicked",(GtkSignalFunc)remove_book,GTK_NOTEBOOK(notebook)); gtk_table_attach_defaults(GTK_TABLE(table),button,5,6,1,2); gtk_widget_show(button); gtk_widget_show(table); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="框架、比例框架、分栏窗口构件">框架、比例框架、分栏窗口构件<a class="anchorjs-link " href="#框架、比例框架、分栏窗口构件" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:12</span></p> <div id="md-view"> ### 框架(Frames) 框架(Frames)可以用于在盒子中封装一个或一组构件,框架本身还可以有一个标签。标签的位置和盒子的风格可以灵活改变。在UI设置中,使用框架还是比较多的,也比较简单。看下面的示例代码吧! ### ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7799cc92a.jpg) ~~~ /*File:frames.c *Date:2014-02-09 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *frames; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"Frame Example!"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "destroy",G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request(window,300,300); /*设置窗口的边框宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),5); /**/ frames = gtk_frame_new(NULL); gtk_container_add(GTK_CONTAINER(window),frames); /*设置框架的标签*/ gtk_frame_set_label(GTK_FRAME(frames),"GTK Frame widget"); /*将标签定位在框架的右边*/ gtk_frame_set_label_align(GTK_FRAME(frames),1.0,0.0); /*设置框架的风格*/ gtk_frame_set_shadow_type(GTK_FRAME(frames),GTK_SHADOW_OUT); gtk_widget_show(frames); gtk_widget_show(window); /* 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ ### ### 比例框架 (Aspect Frames) 比 例框架构件(The aspect frame widget)和框架构件(frame widget)差不多,除了它还会使子构件的外观比例(也就是宽和长的比例)保持一定值,如果需要,还会在构件中增加额外的可用空间。这很有用,例如想 预览一个大的图片。当用户改变窗口的尺寸时,预览器的尺寸应该随之改变,但是外观比例要与原来图片的尺寸保持一致。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7799e3c48.jpg) ~~~ /*File:aspectFrame.c *Date:2014-02-09 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *aspect_frame; GtkWidget *drawing_area; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"Frame Example!"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "destroy",G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request(window,300,300); /*设置窗口的边框宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),5); /**/ aspect_frame = gtk_aspect_frame_new("2x1",/*label*/ 0.5,/*center x*/ 0.5,/*center y*/ 2,/*xsize/ysize = 2*/ FALSE/*ignore child aspect*/); gtk_container_add(GTK_CONTAINER(window),aspect_frame); gtk_widget_show(aspect_frame); /*添加个子控件画图板*/ drawing_area = gtk_drawing_area_new(); gtk_widget_set_size_request(drawing_area,200,200); gtk_container_add(GTK_CONTAINER(aspect_frame),drawing_area); gtk_widget_show(drawing_area); gtk_widget_show(window); /* 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ ### ### 分栏窗口构件 Paned Window Widgets 如 果想要将一个窗口分成两个部分,可以使用分栏窗口构件(The paned window widgets)。窗口两部分的尺寸由用户控制,它们之间有一个凹槽,上面有一个手柄,用户可以拖动此手柄改变两部分的比例。窗口划分可以是水平 (HPaned)或垂直的(VPaned)。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779a03015.jpg) ~~~ /*File:panedWindowWidget.c *Date:2014-02-09 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <stdio.h> /*创建一个消息的列表*/ GtkWidget *create_list(void) { GtkWidget *scrolled_window; GtkWidget *tree_view; GtkListStore *model; GtkTreeIter iter; GtkCellRenderer *cell; GtkTreeViewColumn *column; int i; /*创建一个新的滚动窗口,只有需要时,滚动条才会出现*/ scrolled_window = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); model = gtk_list_store_new(1,G_TYPE_STRING); tree_view = gtk_tree_view_new(); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),tree_view); gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view),GTK_TREE_MODEL(model)); gtk_widget_show(tree_view); /*在窗口添加一些消息*/ for(i = 0; i < 10; i++){ gchar *msg = g_strdup_printf("Message #%d.",i); gtk_list_store_append(GTK_LIST_STORE(model),&iter); gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,msg,-1); g_free(msg); } /*创建列的代表*/ cell = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Message",cell,"text",0,NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view),GTK_TREE_VIEW_COLUMN(column)); gtk_widget_set_size_request(scrolled_window,300,150); return scrolled_window; } /*向文本构件中添加一些文本- 这是当窗口被实例化时调用的回调函数*/ void insert_text(GtkTextBuffer *buffer) { GtkTextIter iter; /*偏移到文本构件的开头*/ gtk_text_buffer_get_iter_at_offset(buffer,&iter,0); gtk_text_buffer_insert(buffer,&iter, "From:jsh@163.com\n" "To:413977243@qq.com\n" "Subject:I Miss You!\n" "\n" "These days have been think you,\nsee you on the QQ no information\n" "are inexplicable pain in my heart,\ncan not let go!\n" " love you 阿辉\n", -1); } /*创建一个滚动的文本区域,用于显示一个信息*/ GtkWidget *create_text(void) { GtkWidget *scrolled_window; GtkWidget *view; GtkTextBuffer *buffer; view = gtk_text_view_new(); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); scrolled_window = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolled_window),view); insert_text(buffer); gtk_widget_show_all(scrolled_window); return scrolled_window; } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *vpaned; GtkWidget *list; GtkWidget *text; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"Frame Example!"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "destroy",G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request(window,300,300); /*设置窗口的边框宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),10); /*在顶级窗口上添加一个垂直分栏窗口构件*/ vpaned = gtk_vpaned_new(); gtk_container_add(GTK_CONTAINER(window),vpaned); gtk_widget_show(vpaned); /*在分栏窗口的两部分各添加一些构件*/ list = create_list(); gtk_paned_add1(GTK_PANED(vpaned),list); gtk_widget_show(list); text = create_text(); gtk_paned_add2(GTK_PANED(vpaned),text); gtk_widget_show(text); gtk_widget_show(window); /* 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="事件驱动(事件盒、固定窗口)">事件驱动(事件盒、固定窗口)<a class="anchorjs-link " href="#事件驱动(事件盒、固定窗口)" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:10</span></p> <div id="md-view"> ### 事件盒 The EventBox 一 些 GTK 构件没有与之相关联的 X 窗口,所以它们只在其父构件上显示其外观。由于这个原因,它们不能接收任何事件,并且,如果它们尺寸设置不正确,它们也不会自动剪裁(译者注:裁剪就是使 构件只显示一部分),这样可能会把界面弄得乱糟糟的。如果要想构件接收事件,可以使用事件盒(EventBox)。 初 一看,事件盒构件好像完全没有什么用。它在屏幕上什么也不画,并且对事件也不做响应。但是,它有一个功能:为它的子构件提供一个 X 窗口。因为许多G T K构件并没有相关联的 X 窗口,所以这一点很重要。虽然没有 X 窗口会节省内存,提高系统性能,但它也有一些弱点。没有 X 窗口的构件不能接收事件,并且对它的任何内容不能实施剪裁。虽然事件盒构件的名称事件盒强调了它的事件处理功能,它也能用于剪裁构件。看下面的具体代码: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7799a2199.jpg) ### 点击将会退出 ~~~ /*File:color.c *Date:2014-01-06 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <gdk/gdk.h> #include <stdlib.h> int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *event_box; GtkWidget *label; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "destroy",G_CALLBACK (gtk_main_quit), (gpointer)window); /*创建一个事件盒,并将它加到顶级窗口上*/ event_box = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(window),event_box); gtk_widget_show(event_box); /*创建一个长标签*/ label = gtk_label_new("点击这里,退出"); gtk_container_add(GTK_CONTAINER(event_box),label); gtk_widget_show(label); /*将标签剪裁短*/ gtk_widget_set_size_request(label,110,20); /**/ gtk_widget_set_events(event_box,GDK_BUTTON_PRESS_MASK); g_signal_connect(GTK_OBJECT(event_box),"button_press_event",G_CALLBACK(gtk_main_quit),NULL); gtk_widget_realize(event_box); gdk_window_set_cursor(event_box->window,gdk_cursor_new(GDK_HAND1)); gtk_widget_show (window); /* 所有的 GTK 程序必须有一个 gtk_main() 函数。程序运行停在这里 * 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ ### 固定容器 Fixed Container 固定容器(The Fixed container)允许将构件放在窗口的固定位置,这个位置是相对于固定容器的左上角的。构件的位置可以动态改变。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7799b522a.jpg) ~~~ /*File:color.c *Date:2014-01-07 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <gdk/gdk.h> #include <glib.h> /*用全局变量储存固定容器里构件的位置*/ gint x = 50; gint y = 50; /*这个回调函数将按钮移动到固定容器的位置*/ void move_button(GtkWidget *widget,GtkWidget *fixed) { x = (x + 30)%300; y = (y + 30)%300; gtk_fixed_move(GTK_FIXED(fixed),widget,x,y); } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *button; GtkWidget *fixed; gint i; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"Fixed Container"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "destroy",G_CALLBACK (gtk_main_quit), NULL); /*设置窗口的边框宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),10); /*创建一个固定容器*/ fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window),fixed); gtk_widget_show(fixed); for(i = 0; i < 3; i++){ /*创建一个按钮*/ button = gtk_button_new_with_label("miss you!"); g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(move_button),fixed); /*将按钮组装到一个固定容器的窗口中*/ gtk_fixed_put(GTK_FIXED(fixed),button,i*50,i*50); gtk_widget_show(button); } gtk_widget_show (window); /* 所有的 GTK 程序必须有一个 gtk_main() 函数。程序运行停在这里 * 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="颜色选择对话框、文件选择控件">颜色选择对话框、文件选择控件<a class="anchorjs-link " href="#颜色选择对话框、文件选择控件" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:07</span></p> <div id="md-view"> ### 颜色选择 Color Selection 颜 色选择(color selection)构件是一个用来交互式地选择颜色的构件。这个组合构件让用户通过操纵RGB值(红绿蓝)和HSV值(色度、饱和度、纯度)来选择颜 色。这是通过调整滑动条(sliders)的值或者文本输入构件的值,或者从一个色度/饱和度/纯度条上选择相应的颜色来实现的。你还可以通过它来设置颜 色的透明性。看下面的代码例子: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77995cd95.jpg) ~~~ /*File:color.c *Date:2014-01-05 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <gdk/gdk.h> #include <glib.h> GtkWidget *colorseldlg = NULL; GtkWidget *drawingarea = NULL; GdkColor color; /*颜色改变处理信号*/ void color_changed_cb(GtkWidget *widget,GtkColorSelection *colorsel) { GdkColor ncolor; gtk_color_selection_get_current_color(colorsel,&ncolor); gtk_widget_modify_bg(drawingarea,GTK_STATE_NORMAL,&ncolor); } /*绘图区事件处理函数*/ gint area_event(GtkWidget *widget,GdkEvent *event,gpointer client_data) { gint handled = FALSE; gint response; GtkColorSelection *colorsel; /*检查是否收到鼠标按键按下*/ if(event->type == GDK_BUTTON_PRESS){ handled = TRUE; /*创建颜色选择对话框*/ if(colorseldlg == NULL){ /*创建一个孤立的颜色选择构件,并需要将其放在某个对话框*/ colorseldlg = gtk_color_selection_dialog_new("选择背景颜色"); } /*获取颜色选择构件*/ colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel); gtk_color_selection_set_previous_color(colorsel,&color); gtk_color_selection_set_current_color(colorsel,&color); gtk_color_selection_set_has_palette(colorsel,TRUE); /*为color_changed 信号设置回调函数,将用户数据设置为颜色选择构件*/ g_signal_connect(GTK_OBJECT(colorsel),"color_changed",G_CALLBACK(color_changed_cb),(gpointer)colorsel); /*显示对话框*/ response = gtk_dialog_run(GTK_DIALOG(colorseldlg)); if(response == GTK_RESPONSE_OK){ /*获取当前颜色,并保存到color中*/ gtk_color_selection_get_current_color(colorsel,&color); }else{ /*设置成原来的颜色*/ gtk_widget_modify_bg(drawingarea,GTK_STATE_NORMAL,&color); } gtk_widget_hide(colorseldlg); } /*只有返回True,才能弹出颜色选择控件*/ return handled; } /*关闭、退出事件处理函数*/ gint destroy_window(GtkWidget *widget,GdkEvent *event,gpointer client_data) { gtk_main_quit(); return TRUE; } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *button; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /**/ gtk_window_set_policy(GTK_WINDOW(window),TRUE,TRUE,TRUE); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 destroy_window() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (GTK_OBJECT(window), "delete_event",G_CALLBACK (destroy_window), (gpointer)window); /*创建绘图区,设置尺寸,捕捉鼠标按键事件*/ drawingarea = gtk_drawing_area_new(); color.red = 0; color.blue = 65535; color.green = 0; /*设置背景颜色*/ gtk_widget_modify_bg(drawingarea,GTK_STATE_NORMAL,&color); /*设定绘图区域的大小*/ gtk_widget_set_size_request(GTK_WIDGET(drawingarea),200,200); /*设置成按钮事件*/ gtk_widget_set_events(drawingarea,GDK_BUTTON_PRESS_MASK); g_signal_connect(GTK_OBJECT(drawingarea),"event",GTK_SIGNAL_FUNC(area_event),(gpointer)drawingarea); gtk_container_add(GTK_CONTAINER(window),drawingarea); /* 最后一步是显示新创建的按钮和窗口 */ gtk_widget_show (drawingarea); gtk_widget_show (window); /* 所有的 GTK 程序必须有一个 gtk_main() 函数。程序运行停在这里 * 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ ### 文件选择 File Selections 文件选择(file selection)构件是一种快速、简单的显示文件对话框的方法。它带有“Ok”、“Cancel”、“Help”按钮,可以极大地减少编程时间。看下面的代码: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779979b4a.jpg) ~~~ /*File:color.c *Date:2014-01-05 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <gdk/gdk.h> #include <glib.h> /*获得文件名,并将它打印到控制台上*/ void file_ok_sel(GtkWidget *w,GtkFileSelection *fs) { g_print("%s\n",gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs))); } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *filew; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /*创建一个新的文件选择构件*/ filew = gtk_file_selection_new("文件选择对话框"); g_signal_connect (GTK_OBJECT(filew), "destroy",G_CALLBACK (gtk_main_quit), NULL); /*为ok_button按钮设置回调函数,链接到file_ok_sel 函数*/ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button),"clicked",G_CALLBACK(file_ok_sel),filew); /*为cancel_button设置回调函数*/ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button),"clicked",G_CALLBACK(gtk_main_quit),filew); /*设置文件名,不如这个一个文件保存对话框,我们给了一个缺省文件名*/ gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew),"1111.png"); gtk_widget_show (filew); /* 所有的 GTK 程序必须有一个 gtk_main() 函数。程序运行停在这里 * 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="状态栏、文本输入构件、组合框">状态栏、文本输入构件、组合框<a class="anchorjs-link " href="#状态栏、文本输入构件、组合框" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:05</span></p> <div id="md-view"> ### 状态栏 Statusbars 状态栏(Statusbars)是一些简单的构件,一般用来显示文本消息。它将文本消息压入到一个栈里面,当弹出当前消息时,将重新显示前一条文本消息。看下面具体的代码实现: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779869703.jpg) ~~~ /*File:statusbar.c *Date:2013-12-22 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> #include <stdlib.h> #include <glib.h> GtkWidget *status_bar; void push_item(GtkWidget *widget,gpointer data) { static int count = 1; char buf[20] = {'\0'}; g_snprintf(buf,20,"Item %d",count++); //将新消息加到状态栏 gtk_statusbar_push(GTK_STATUSBAR(status_bar),GPOINTER_TO_INT(data),buf); return; } void pop_item(GtkWidget *widget,gpointer data) { //删除在栈中给定上下文标识符最上面的一个消息 gtk_statusbar_pop(GTK_STATUSBAR(status_bar),GPOINTER_TO_INT(data)); return; } int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *vbox; gint context_id; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),"GTK 状态栏工具"); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); vbox = gtk_vbox_new(FALSE,1); gtk_container_add(GTK_CONTAINER(window),vbox); gtk_widget_show(vbox); //创建一个状态栏 status_bar = gtk_statusbar_new(); gtk_box_pack_start(GTK_BOX(vbox),status_bar,TRUE,TRUE,0); gtk_widget_show(status_bar); //获得上下文的标识符 context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar),"Statusbar example"); button = gtk_button_new_with_label("push_item"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(push_item),GINT_TO_POINTER(context_id)); gtk_box_pack_start(GTK_BOX(vbox),button,TRUE,TRUE,2); gtk_widget_show(button); button = gtk_button_new_with_label("pop last item"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(pop_item),GINT_TO_POINTER(context_id)); gtk_box_pack_start(GTK_BOX(vbox),button,TRUE,TRUE,2); gtk_widget_show(button); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ ### 文本输入构件 Text Entries 文本输入构件(Entry widget)允许在一个单行文本框里输入和显示一行文本。文本可以用函数进行操作,如将新的文本替换、前插、追加到文本输入构件的当前内容中。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7798801bb.jpg) ~~~ /*File:text_entry.c *Date:2013-12-28 *Author:sjin *Mail:413977243@qq.com */ #include<gtk/gtk.h> #include <stdio.h> #include <stdlib.h> static GtkWidget* entry1; static GtkWidget* entry2; void on_button_clicked (GtkWidget* button,gpointer data) { /*void gtk_entry_set_text(Gtk_Entry *entry,const gchr *text) * 将新的内容取代文本输入构件当前的内容。 *const gchar *gtk_entry_get_text(GtkEntry *entry) * 获得当前文本输入构件的内容 */ if((int)data == 1){ gtk_entry_set_text(GTK_ENTRY(entry1),""); gtk_entry_set_text(GTK_ENTRY(entry2),""); } else if ((int)data == 2){ const gchar* username = gtk_entry_get_text(GTK_ENTRY(entry1)); const gchar* password = gtk_entry_get_text(GTK_ENTRY(entry2)); g_print("用户名是:%s",username); g_print("\n"); g_print("密码是:%s\n",password); } else if((int)data == 3){ /*改变文本空的可编辑状态*/ gtk_editable_set_editable(GTK_EDITABLE(entry1),GTK_TOGGLE_BUTTON(button)->active); gtk_editable_set_editable(GTK_EDITABLE(entry2),GTK_TOGGLE_BUTTON(button)->active); } } int main(int argc,char* argv[]) { GtkWidget* window; GtkWidget* box; GtkWidget* box1; GtkWidget* box2; GtkWidget* box3; GtkWidget* label1; GtkWidget* label2; GtkWidget* button; GtkWidget* sep; //初始化 gtk_init(&argc,&argv); //设置窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL); gtk_window_set_title(GTK_WINDOW(window),"登录窗口"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window),20); box = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box); box1 = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box),box1,FALSE,FALSE,5); box2 = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box),box2,FALSE,FALSE,5); sep = gtk_hseparator_new();//分割线 gtk_box_pack_start(GTK_BOX(box),sep,FALSE,FALSE,5); box3 = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box),box3,TRUE,TRUE,5); label1 = gtk_label_new("用户名:"); entry1 = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(box1),label1,FALSE,FALSE,5); gtk_box_pack_start(GTK_BOX(box1),entry1,FALSE,FALSE,5); label2 = gtk_label_new("密 码:"); entry2 = gtk_entry_new(); /*设置输入文本不可见*/ gtk_entry_set_visibility(GTK_ENTRY(entry2),FALSE); gtk_box_pack_start(GTK_BOX(box2),label2,FALSE,FALSE,5); gtk_box_pack_start(GTK_BOX(box2),entry2,FALSE,FALSE,5); button = gtk_check_button_new_with_label("Editable"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button_clicked),(gpointer)3); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE); gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,10); gtk_widget_show(button); button = gtk_button_new_with_label("清空"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button_clicked),(gpointer)1); gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,10); gtk_widget_show(button); button = gtk_button_new_with_label("确认"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button_clicked),(gpointer)2); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),window); gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,5); gtk_widget_show(button); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ ### 组合框 Combo Box 组合框(combo box)是另一个很简单的构件,实际上它仅仅是其它构件的集合。从用户的观点来说,这个构件是由一个文本输入构件和一个下拉菜单组成的,用户可以从一个预先定义的列表里面选择一个选项,同时,用户也可以直接在文本框里面输入文本. ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7799478b4.jpg) ~~~ #include <gtk/gtk.h> void callback(GtkWidget *button,gpointer data) { printf("组合框发生改变\n"); if((int)data == 1){ gchar *ptr = gtk_entry_get_text(GTK_ENTRY(button)); printf("组合框A发生改变,内容是:%s\n",ptr); }else if((int)data == 2) { gchar *ptr = gtk_entry_get_text(GTK_ENTRY(button)); printf("组合框A发生改变,内容是:%s\n",ptr); } } GtkWidget *create_item (gint i) { GtkWidget *item; GtkWidget *label; GtkWidget *hbox; GtkWidget *image; hbox = gtk_hbox_new(FALSE,0); switch(i){ case 1: image = gtk_image_new_from_stock(GTK_STOCK_YES,GTK_ICON_SIZE_MENU); label = gtk_label_new("列表项一"); break; case 2: image = gtk_image_new_from_stock(GTK_STOCK_NO,GTK_ICON_SIZE_MENU); label = gtk_label_new("列表项二"); break; case 3: image = gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU); label = gtk_label_new("列表项三"); break; case 4: image = gtk_image_new_from_stock(GTK_STOCK_OK,GTK_ICON_SIZE_MENU); label = gtk_label_new("列表项四"); break; case 5: image = gtk_image_new_from_stock(GTK_STOCK_CANCEL,GTK_ICON_SIZE_MENU); label = gtk_label_new("列表项五"); break; } gtk_box_pack_start(GTK_BOX(hbox),image,FALSE,FALSE,2); gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE,2); item = gtk_list_item_new(); gtk_container_add(GTK_CONTAINER(item),hbox); gtk_widget_show_all(item); return item; } int main(int argc,char* argv[]) { GtkWidget *window; GtkWidget *combo; GtkWidget *label; GtkWidget *vbox; GList *items = NULL; GtkWidget *item; items =g_list_append(items,"列表项A"); items =g_list_append(items,"列表项B"); items =g_list_append(items,"列表项C"); items =g_list_append(items,"列表项D"); items =g_list_append(items,"列表项E"); gtk_init(&argc,&argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); gtk_window_set_title(GTK_WINDOW(window),"下拉列表框"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window),20); vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); label = gtk_label_new("组合框A"); gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,5); combo = gtk_combo_new(); gtk_box_pack_start(GTK_BOX(vbox),combo,FALSE,FALSE,5); gtk_combo_set_popdown_strings(GTK_COMBO(combo),items); g_signal_connect(G_OBJECT(GTK_COMBO(combo)->entry),"changed",G_CALLBACK(callback),(gpointer)1); /************另一种创建的方式****************/ label = gtk_label_new("组合框B"); gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,5); combo = gtk_combo_new(); gtk_box_pack_start(GTK_BOX(vbox),combo,FALSE,FALSE,5); item = create_item(1); gtk_combo_set_item_string(GTK_COMBO(combo),GTK_ITEM(item),"项目一"); gtk_container_add(GTK_CONTAINER(GTK_COMBO(combo)->list),item); item = create_item(2); gtk_combo_set_item_string(GTK_COMBO(combo),GTK_ITEM(item),"项目二"); gtk_container_add(GTK_CONTAINER(GTK_COMBO(combo)->list),item); item = create_item(3); gtk_combo_set_item_string(GTK_COMBO(combo),GTK_ITEM(item),"项目三"); gtk_container_add(GTK_CONTAINER(GTK_COMBO(combo)->list),item); item = create_item(4); gtk_combo_set_item_string(GTK_COMBO(combo),GTK_ITEM(item),"项目四"); gtk_container_add(GTK_CONTAINER(GTK_COMBO(combo)->list),item); item = create_item(5); gtk_combo_set_item_string(GTK_COMBO(combo),GTK_ITEM(item),"项目五"); gtk_container_add(GTK_CONTAINER(GTK_COMBO(combo)->list),item); g_signal_connect(G_OBJECT(GTK_COMBO(combo)->entry),"changed",G_CALLBACK(callback),(gpointer)2); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="对话框">对话框<a class="anchorjs-link " href="#对话框" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:03</span></p> <div id="md-view"> ### 对话框        对话框是一类GtkWindow,它用于提供顶层窗口。它可以为用户提供消息,可以获得用户信息,或者提供一些简短的动作。       对话款构件被一个水平分割线分隔成两半。上半部放置的是用户界面的主要部分。下半部被称为动作区域,它包括一系列的按钮。当点击,每个按钮会发出一个唯一标识的信号,告诉程序员哪个按钮被点击了。       一般来说,对话框构件可以被看做一个窗口,因为它从GtkWindow类继承而来。然而,当您有多个窗口时,父亲-孩子的关系应该建立在对话框和顶层窗口之间,对话框注定是顶层窗口的补充。 ~~~ typedef struct { GtkWidget *vbox; GtkWidget *action_area; } GtkDialog; ~~~ GtkDialog提供了两个公共成员,包括一个横向按钮的盒子,称为动作区域,以及一个纵向盒子。动作区域包括所有的按钮,在对话框下部排列着。通过GtkHbuttonBox,您可以手工添加按钮,但是通常您应该使用GtkDialog提供的函数来添加动作区域构件。 具体看下面一个简单的例子: ~~~ /*File:dialogs.c *Date:2013-12-16 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> //无模式窗口 //#define SCHEMALESS_WINDOW void button_click(GtkWidget *widget,GtkWindow *parent) { GtkWidget *dialog; GtkWidget *label; GtkWidget *image; GtkWidget *hbox; /*GtkWidget * gtk_dialog_new_with_buttons( * const gchar *title,对话框标题 * GtkWindow *parent,对话框父窗口 * GtkDialogFlags flags, * const gchar *first_button_text,动作区域按钮列表 * ...); * falgs:GTK_DIALOG_MODAL:对话框始终保持在父窗口的上部,直到关闭,防止父窗口交互 * GTK_DIALOG_DESTROY_WITH_PARENT:父窗口销毁,对话框也销毁 * GTK_DIALOG_NO_SEPARATOR:不显示分割线 * * */ #ifndef SCHEMALESS_WINDOW dialog = gtk_dialog_new_with_buttons("我的第一个对话框",parent,GTK_DIALOG_MODAL,GTK_STOCK_OK,GTK_RESPONSE_OK,NULL); #else dialog = gtk_dialog_new_with_buttons("我的第一个对话框",parent,GTK_DIALOG_DESTROY_WITH_PARENT,GTK_STOCK_OK,GTK_RESPONSE_OK,NULL); #endif /*设置分割线是否隐藏:FALSE:隐藏。*/ gtk_dialog_set_has_separator(GTK_DIALOG(dialog),FALSE); label = gtk_label_new("the button was clicked!"); /*GtkWidget * gtk_image_new_from_stock(const gchar *stock_id, * GtklconSize size) * 创建一个预制的Gtkimage构件,当载入一个图片时,还需要指定图片的 *大小,如果图片没有找到,GTK会自动寻找一个自制的图标 * size :参数 GTK_ICON_SIZE_INVALID:未指定大小 * GTK_ICON_SIZE_MENU : 16X16像素 * GTK_ICON_SIZE_SMALL_TOOLBAR: 18X18像素 * GTK_ICON_SIZE_LARGE_TOOLBAR: 24X24像素 * GTK_ICON_SIZE_BUTTON: 24X24像素 * GTK_ICON_SIZE_DND: 32X32像素 * GTK_ICON_SIZE_DIALOG: 48X48像素 *还有另外两个加载图片的函数 *GtkWidget*gtk_image_new_from_file(const gchar *filename) *GtkWidget *gtk_image_new_from_pixbuf(GdkPixbuf *pixbuf) * */ image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,GTK_ICON_SIZE_DIALOG); hbox = gtk_hbox_new(FALSE,5); gtk_container_set_border_width(GTK_CONTAINER(hbox),10); gtk_box_pack_start_defaults(GTK_BOX(hbox),image); gtk_box_pack_start_defaults(GTK_BOX(hbox),label); gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),hbox); gtk_widget_show_all(dialog); #ifndef SCHEMALESS_WINDOW /*显示对话框*/ gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); #else g_signal_connect(G_OBJECT(dialog),"response",G_CALLBACK(gtk_widget_destroy),NULL); #endif } int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *button; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),"对话框练习"); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); //创建按钮 button = gtk_button_new_with_mnemonic("clicked me"); gtk_container_add(GTK_CONTAINER(window),button); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(button_click),(gpointer)window); gtk_widget_show(button); gtk_widget_show_all(window); gtk_main(); return 0; } ~~~ 编译时有两种模式,-DSCHEMALESS_WINDOW 是无模式窗口,和模式窗口(不能和父窗口交互,永远在父窗口上面)。 运行: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7797b2361.jpg) 另外一个对话框的应用: ~~~ /*File:dialogs3.c *Date:2013-12-16 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> int main(int argc, char*argv[]) { GtkWidget *dialog; GtkWidget *table; GtkWidget *user,*real,*home,*host; GtkWidget *lbl1,*lbl2,*lbl3,*lbl4; gint result; //初始化GTK gtk_init(&argc,&argv); /*GtkWidget * gtk_dialog_new_with_buttons( * const gchar *title,对话框标题 * GtkWindow *parent,对话框父窗口 * GtkDialogFlags flags, * const gchar *first_button_text,动作区域按钮列表 * ...); * falgs:GTK_DIALOG_MODAL:对话框始终保持在父窗口的上部,直到关闭,防止父窗口交互 * GTK_DIALOG_DESTROY_WITH_PARENT:父窗口销毁,对话框也销毁 * GTK_DIALOG_NO_SEPARATOR:不显示分割线 * * */ dialog = gtk_dialog_new_with_buttons("用户信息编辑窗口",NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK,GTK_RESPONSE_OK, GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, NULL); //设置缺省按钮 gtk_dialog_set_default_response(GTK_DIALOG(dialog),GTK_RESPONSE_OK); //创建4个条目,告诉用户输入的数据 lbl1 = gtk_label_new("User Name"); lbl2 = gtk_label_new("Real Name"); lbl3 = gtk_label_new("Home Dir"); lbl4 = gtk_label_new("Host Name"); user = gtk_entry_new(); real = gtk_entry_new(); home = gtk_entry_new(); host = gtk_entry_new(); //设置条目的缺省值 gtk_entry_set_text(GTK_ENTRY(user),g_get_user_name()); gtk_entry_set_text(GTK_ENTRY(real),g_get_real_name()); gtk_entry_set_text(GTK_ENTRY(home),g_get_home_dir()); gtk_entry_set_text(GTK_ENTRY(host),g_get_host_name()); //表组装 table = gtk_table_new(4,2,FALSE); gtk_table_attach_defaults(GTK_TABLE(table),lbl1,0,1,0,1); gtk_table_attach_defaults(GTK_TABLE(table),lbl2,0,1,1,2); gtk_table_attach_defaults(GTK_TABLE(table),lbl3,0,1,2,3); gtk_table_attach_defaults(GTK_TABLE(table),lbl4,0,1,3,4); gtk_table_attach_defaults(GTK_TABLE(table),user,1,2,0,1); gtk_table_attach_defaults(GTK_TABLE(table),real,1,2,1,2); gtk_table_attach_defaults(GTK_TABLE(table),home,1,2,2,3); gtk_table_attach_defaults(GTK_TABLE(table),host,1,2,3,4); gtk_table_set_row_spacings(GTK_TABLE(table),5); gtk_table_set_col_spacings(GTK_TABLE(table),5); gtk_container_set_border_width(GTK_CONTAINER(table),5); gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),table); gtk_widget_show_all(dialog); //运行和输出对话框 result = gtk_dialog_run(GTK_DIALOG(dialog)); switch(result){ case GTK_RESPONSE_NONE: /*-1 * 对话框被窗口管理器销毁或通过gtk_widget_destroy()有其他程序销毁。 * 如果构件没有设置一个相应标识,会返回它。 */ break; case GTK_RESPONSE_REJECT: /* -2 * 这个标识没有和对话框内置的任何按钮相关联,可以任意使用它 * */ break; case GTK_RESPONSE_ACCEPT: /* -3 * 这个标识没有和对话框内置的任何按钮相关联,可以任意使用它 * */ break; case GTK_RESPONSE_DELETE_EVENT: /* -4 * 每个对话框都会自动连接到delete-event信号,当gtk_dialog_run() * 运行是,这个标识会被返回,而且delete-event会被终止、不会像 * 往常那样销毁窗口 * */ break; case GTK_RESPONSE_OK: /* -5 * GTK_STOCK_OK 被点击 */ g_print("User Name:\t%s\n",gtk_entry_get_text(GTK_ENTRY(user))); g_print("Real Name:\t%s\n",gtk_entry_get_text(GTK_ENTRY(real))); g_print("Home Dir:\t%s\n",gtk_entry_get_text(GTK_ENTRY(home))); g_print("Host Name:\t%s\n",gtk_entry_get_text(GTK_ENTRY(host))); break; case GTK_RESPONSE_CANCEL: /*-6 * GTK_STOCK_CANCEL被点击 * */ g_print("cancel is press!\n"); break; case GTK_RESPONSE_CLOSE: /* -7 *GTK_STOCK_CLOSE被点击 */ break; case GTK_RESPONSE_YES: /* -8 *GTK_STOCK_YES被点击 */ break; case GTK_RESPONSE_NO: /* -9 *GTK_STOCK_NO被点击 */ break; case GTK_RESPONSE_APPLY: /* -10 *GTK_STOCK_APPLY被点击 */ break; case GTK_RESPONSE_HELP: /* -11 *GTK_STOCK_HELP被点击 */ break; default: g_print("something wrong!\n"); break; } gtk_widget_destroy(dialog); //gtk_main(); return 0; } ~~~ 运行结果如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7797c90bf.jpg) **消息对话框**       消息对话框用于下列四种消息:一般信息、错误信息、警告和问题。对话框的类型决定了显示的图表类型、对话框标题和添加的按钮。       还有一种通用类型的对话框,它对内容没有任何假设。在多数情况下,您不需要使用它,因为上述四种类型基本上满足了大部分需求。       重新创建GtkMessageDialog构件是很容易的。前面的两个例子实现了一个简单的消息对话框,但是GtkMessageDialog已经提供了这个功能,因此您不需要重新创建这个构件。使用GtkMessageDialog节省了代码,而且避免您反复重新创建这种构件,其实大部分应用程序反复使用GtkMessageDialog。它还为所有GTK+应用程序提供了一个统一的外观。  具体看下面的示例: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7797df3b7.jpg) 具体代码如下: ~~~ /*File: message.c *Date:2013-12-21 *Author:sjin *Mail:43977243@qq.com */ #include <gtk/gtk.h> static void on_button_clicked(GtkWidget* button,gpointer data) { GtkWidget* dialog; GtkMessageType type; gchar* message; switch((int)data){ case 1: message = "这是个信息提示对话框."; type = GTK_MESSAGE_INFO; break; case 2: message = "这是个错误提示对话框"; type = GTK_MESSAGE_ERROR; break; case 3: message = "这是个问题提示对话框"; type = GTK_MESSAGE_QUESTION; break; case 4: message = "这是个警告提示对话框"; type = GTK_MESSAGE_WARNING; break; default: break; } /*GtkWidget * gtk_message_dialog_new(GtkWindow *parent, * GtkDialogFlags flags, * GtkMessageType type, * GtkButtonsType buttons, * const gchar * message_format, * ...); * type :枚举的五个可能值: * GTK_MESSAGE_INFO:显示用户的一般性消息 * GTK_MESSAGE_WARNING:一个警告信息,表示发生了非致命的错误 * GTK_MESSAGE_QUESTION:询问用户一个问题,用户必须做出选择。 * GTK_MESSAGE_ERROR:警告信息,标识发生了一个致命的错误 * GTK_MESSAGE_OTHER:一般类型的消息 * buttons:显示什么类型的按钮 * GTK_BUTTONS_NONE:不添加任何按钮。 * GTK_BUTTONS_OK:添加GTK_STOCK_OK按钮 * GTK_BUTTONS_CLOSE:添加GTK_STOCK_CLOSE按钮 * GTK_BUTTONS_CANCEL:添加GTK_STOCK_CANCEL按钮 * GTK_BUTTONS_YES_NO:添加GTK_STOCK_YES和GTK_STOCK_NO * GTK_BUTTONS_OK_CANCEL: ... * 最后一个参数是显示对话框中的内容 * * void gtk_message_dialog_set_format_secondary_text(GtkMessageDialog*dialog, * const gchar *message_format, * ...); * 为消息对话框添加第二段文本,他会导致第一个文本被设置成粗体。这个功能 * 非常有用,它允许您在第一段文字中写一个简短的概要,在第二段文本中详细 * 描述。通过gtk_message_set_format_secondary_markup()来设置文本格式 * */ dialog = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,type,GTK_BUTTONS_OK,message); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } int main(int argc,char* argv[]) { GtkWidget* window; GtkWidget* frame; GtkWidget* box; GtkWidget* button1; GtkWidget* button2; GtkWidget* button3; GtkWidget* button4; gtk_init(&argc,&argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"创建消息框"); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL); gtk_container_set_border_width(GTK_CONTAINER(window),20); frame = gtk_frame_new("四种消息对话框"); gtk_container_add(GTK_CONTAINER(window),frame); box = gtk_hbox_new(TRUE,0); gtk_container_add(GTK_CONTAINER(frame),box); gtk_container_set_border_width(GTK_CONTAINER(box),20); button1 = gtk_button_new_from_stock(GTK_STOCK_DIALOG_INFO); gtk_box_pack_start(GTK_BOX(box),button1,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button1),"clicked",G_CALLBACK(on_button_clicked),(gpointer)1); /*GtkWidget * gtk_button_new_from_stock(const gchar *stock_id); * GTK内部保存的条目:图片和文字。stock_id:对应的ID */ button2 = gtk_button_new_from_stock(GTK_STOCK_DIALOG_ERROR); gtk_box_pack_start(GTK_BOX(box),button2,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button2),"clicked",G_CALLBACK(on_button_clicked),(gpointer)2); button3 = gtk_button_new_from_stock(GTK_STOCK_DIALOG_QUESTION); gtk_box_pack_start(GTK_BOX(box),button3,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button3),"clicked",G_CALLBACK(on_button_clicked),(gpointer)3); button4 = gtk_button_new_from_stock(GTK_STOCK_DIALOG_WARNING); gtk_box_pack_start(GTK_BOX(box),button4,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button4),"clicked",G_CALLBACK(on_button_clicked),(gpointer)4); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ **关于对话框**        GtkAboutDialog构件为您提供了一个简单方式,来显示程序的“关于“信息。通常,当用户点GTK_STOCK_ABOUT菜单项时,这个对话框会显示出来。然而,我们要到第九章才会谈到菜单,因此我们的例子对话框就是用顶层窗口。        用GtkAboutDialog可以显示不同类型的信息。这包括应用程序的名字、版权、当前版本、授权协议、作者、文档、美工和翻译。因为不是每个程序都有这些内容,每一个属性都是可选的。主窗口只显示基本信息,在Figure 5-4中可以看到,连同作者信息。 看下面示例图片:及代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7798218d2.jpg) ~~~ /*File: aboutdialogs.c *Date:2013-12-21 *Author:sjin *Mail:43977243@qq.com */ #include <gtk/gtk.h> int main(int argc,char* argv[]) { GtkWidget *dialog; GdkPixbuf *logo; GError *error = NULL; const gchar *authors[] ={ "Kyle Loudon", "sjin", NULL }; const gchar *documenters[]={ "指针操作", "递归", "算法", "链表", "栈和队列", "集合", "哈希表", "树", NULL }; const gchar * translators = "肖翔\n陈珂"; //初始化环境 gtk_init(&argc,&argv); //创建对话框 dialog = gtk_about_dialog_new(); //创建一个图标 logo = gdk_pixbuf_new_from_file("./logo.jpg",&error); if(error == NULL){ gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog),logo); } else { if(error->domain == GDK_PIXBUF_ERROR){ g_print("GdkPixbuf Error : %s\n",error->message); } else if(error->domain == G_FILE_ERROR){ g_print("GFileError : %s\n",error->message); } else { g_print("an error in the domain : %d has occured!\n",error->domain); } } //设置显示在主对话框上的数据 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog),"算法精解-C语言描述"); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog),"1.0"); gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog),"(C)2007 Andrew Krause"); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog),"我的第一本算法书籍"); //设置作者,文档,翻译 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog),authors); gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog),documenters); gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog),translators); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return FALSE; } ~~~ 下面是另一种实现思路: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779844277.jpg) ~~~ /*File:about.c *Date:2013-12-22 *Author:sjin *Mail:413977243@qq.com * */ #include <gtk/gtk.h> static GtkWidget* credits_window; GtkWidget* create_credits() { GtkWidget* window; GtkWidget* vbox; GtkWidget* notebook; GtkWidget* page; GtkWidget* label; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"开发人员"); vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); //这里使用了notebook notebook = gtk_notebook_new(); gtk_box_pack_start(GTK_BOX(vbox),notebook,FALSE,FALSE,5); page = gtk_vbox_new(FALSE,0); label = gtk_label_new("Kyle Loudon"); gtk_box_pack_start(GTK_BOX(page),label,FALSE,FALSE,5); label = gtk_label_new("sjin"); gtk_box_pack_start(GTK_BOX(page),label,FALSE,FALSE,5); label = gtk_label_new("作者"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook),page,label); page = gtk_vbox_new(FALSE,0); label = gtk_label_new("集合"); gtk_box_pack_start(GTK_BOX(page),label,FALSE,FALSE,5); label = gtk_label_new("文档"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook),page,label); page = gtk_vbox_new(FALSE,0); label = gtk_label_new("肖翔\n陈珂"); gtk_box_pack_start(GTK_BOX(page),label,FALSE,FALSE,5); label = gtk_label_new("翻译"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook),page,label); gtk_widget_show_all(window); return window; } void show_credits() { credits_window = create_credits(); gtk_widget_show(credits_window); } int main(int argc,char* argv[]) { GtkWidget* bbox; GtkWidget* vbox; GtkWidget* label; GtkWidget* window; GtkWidget* sep; GtkWidget* image; GtkWidget* button; gtk_init(&argc,&argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); gtk_window_set_title(GTK_WINDOW(window),"关于对话框"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window),10); vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); image = gtk_image_new_from_file("logo.jpg"); gtk_box_pack_start(GTK_BOX(vbox),image,FALSE,FALSE,5); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label),"<span><big>算法精解-C语言描述</big></span>"); gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,5); label = gtk_label_new("版权所有:机械工业出版社\n 作者:Kyle Loudon"); gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,5); sep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox),sep,FALSE,FALSE,5); bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox),GTK_BUTTONBOX_EDGE); gtk_box_pack_start(GTK_BOX(vbox),bbox,FALSE,FALSE,5); button = gtk_button_new_with_label("credits"); gtk_box_pack_start(GTK_BOX(bbox),button,FALSE,FALSE,25); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(show_credits),NULL); button = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_main_quit),NULL); gtk_box_pack_start(GTK_BOX(bbox),button,FALSE,FALSE,35); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ 参考资料: [http://guoyinghui2012.blog.163.com/blog/static/20871720020126219391244/](http://guoyinghui2012.blog.163.com/blog/static/20871720020126219391244/) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="标签控件、箭头按钮、工具提示对象、进度条">标签控件、箭头按钮、工具提示对象、进度条<a class="anchorjs-link " href="#标签控件、箭头按钮、工具提示对象、进度条" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:22:00</span></p> <div id="md-view"> ### 标签 Labels 标签(Labels)是 GTK 中最常用的构件,实际上它很简单。因为没有相关联的 X 窗口,标签不能引发信号。如果需要获取或引发信号,可以将它放在一个事件盒中,或放在按钮构件里面。 下面是Labels的使用一个实例,点击按钮,可以打印原来标签的内容,并设置新的内容,具体代码如下:  ~~~ /*File:label.c *Date:2013-12-13 *Author:sjin *Mail:413977243@qq.com */ #include<gtk/gtk.h> GtkWidget *label1; void callBack(GtkWidget *widget,gpointer data) { printf("label1 = %s\n",gtk_label_get_text(GTK_LABEL(label1))); gtk_label_set_text(GTK_LABEL(label1),(char*)data); sleep(1); gtk_main_quit(); } int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *box; GtkWidget *label2; GtkWidget *label3; GtkWidget *label4; GtkWidget *frame1; GtkWidget *frame2; GtkWidget *frame3; GtkWidget *frame4; GtkWidget *button; gchar *title ; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),"多种样式的标签"); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); //创建盒子 box = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box); //创建框架1 frame1 = gtk_frame_new("标签一"); label1 = gtk_label_new("这是第一个标签,居左边的。This is the first label."); gtk_container_add(GTK_CONTAINER(frame1),label1); /*void gtk_label_set_justify(GtkLabel *label, GtkJustification jtype); * jtype 值:GTK_JUSTIFY_LEFT :左对齐 * GTK_JUSTIFY_RIGHT:右对齐 * GTK_JUSTIFY_CENTER:居中对齐(默认 ) * GTK_JUSTIFY_FILL:充满 */ gtk_label_set_justify(GTK_LABEL(label1),GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(box),frame1,FALSE,FALSE,5); frame2 = gtk_frame_new("标签二"); label2 = gtk_label_new("这是第二个标签,它是多行的。\n这还是第二个标签的内容,它是居右边的。"); gtk_container_add(GTK_CONTAINER(frame2),label2); gtk_label_set_justify(GTK_LABEL(label2),GTK_JUSTIFY_RIGHT); //设置下划线 gtk_label_set_pattern(GTK_LABEL(label2),"__ __ __ "); gtk_box_pack_start(GTK_BOX(box),frame2,FALSE,FALSE,5); frame3 = gtk_frame_new("标签三"); label3 = gtk_label_new(NULL); //标记语言形式 title = "<span foreground=\"red\"><big><i>这是第三个标签。\n它被格式化成红色了,并且字体也大了。</i></big></span>"; gtk_container_add(GTK_CONTAINER(frame3),label3); gtk_label_set_markup(GTK_LABEL(label3),title); gtk_box_pack_start(GTK_BOX(box),frame3,FALSE,FALSE,5); frame4 = gtk_frame_new("标签四"); label4 = gtk_label_new("这也是一个多行标签,它的换行方式和上一个有所不同,主要是编辑手段不一样了,请仔细查看一下源码就会明白怎么回事了。"); gtk_label_set_justify(GTK_LABEL(label1),GTK_JUSTIFY_LEFT); //自动换行函数 gtk_label_set_line_wrap(GTK_LABEL(label4),TRUE); gtk_container_add(GTK_CONTAINER(frame4),label4); gtk_box_pack_start(GTK_BOX(box),frame4,FALSE,FALSE,5); button = gtk_button_new_with_label("set label1"); gtk_box_pack_start(GTK_BOX(box),button,FALSE,FALSE,5); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callBack),"set label1 111"); gtk_container_add(GTK_CONTAINER(window),button); gtk_widget_show(button); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ 运行结果: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77976cd0f.jpg) ### 箭头 Arrows 箭头构件(Arrow widget)画一个箭头,面向几种不同的方向,并有几种不同的风格。在许多应用程序中,常用于创建带箭头的按钮。和标签构件一样,它不能引发信号。下面是一个简单的示例: ~~~ /*File:arrow.c *Date:2013-12-15 *Author:sjin *Mail:413977243@qq.com * */ #include<gtk/gtk.h> //创建自己按钮的函数 GtkWidget * create_arrow_button(GtkArrowType arrowtype, GtkShadowType shadowtype ) { GtkWidget *button; GtkWidget *arrow; button = gtk_button_new(); /*void gtk_arrow_new(GtkArrowType arrow_type,GtkShadowType shadow_type); * 创建箭头, * arrow_type:箭头方向; * GTK_ARROW_UP:向上 * GTK_ARROW_DOWN:向下 * GTK_ARROW_LEFT:向左 * GTK_ARROW_RIGHT:向右 * shadow_type:箭头阴影类型 * GTK_SHADOW_IN: * GTK_SHADOW_OUT(): * GTK_SHADOW_ETCHED_IN: * GTK_SHADOW_ETCHED_OUT: * */ arrow = gtk_arrow_new(arrowtype,shadowtype); gtk_container_add(GTK_CONTAINER(button),arrow); gtk_widget_show(arrow); return button; } void callBack(GtkWidget *widget,gchar *data) { printf("### %s is press\n",(char *)data); } //主函数 int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *box; GtkWidget *arrow1; GtkWidget *arrow2; GtkWidget *arrow3; GtkWidget *arrow4; gchar *title = "方向按钮"; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),title); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); //创建盒子 box = gtk_hbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box); gtk_widget_show(box); //创建带箭头的按钮,调用自定义的函数 arrow1 = create_arrow_button(GTK_ARROW_LEFT,GTK_SHADOW_IN); g_signal_connect(G_OBJECT(arrow1),"clicked",G_CALLBACK(callBack),"向左"); gtk_box_pack_start(GTK_BOX(box),arrow1,FALSE,FALSE,13); gtk_widget_show(arrow1); arrow2 = create_arrow_button(GTK_ARROW_UP,GTK_SHADOW_OUT); g_signal_connect(G_OBJECT(arrow2),"clicked",G_CALLBACK(callBack),"向上"); gtk_box_pack_start(GTK_BOX(box),arrow2,FALSE,FALSE,13); gtk_widget_show(arrow2); arrow3 = create_arrow_button(GTK_ARROW_DOWN,GTK_SHADOW_ETCHED_IN); g_signal_connect(G_OBJECT(arrow3),"clicked",G_CALLBACK(callBack),"向下"); gtk_box_pack_start(GTK_BOX(box),arrow3,FALSE,FALSE,13); gtk_widget_show(arrow3); arrow4 = create_arrow_button(GTK_ARROW_RIGHT,GTK_SHADOW_ETCHED_OUT); g_signal_connect(G_OBJECT(arrow4),"clicked",G_CALLBACK(callBack),"向右"); gtk_box_pack_start(GTK_BOX(box),arrow4,FALSE,FALSE,13); gtk_widget_show(arrow4); gtk_widget_show(window); gtk_main(); return FALSE; } ~~~ ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779786af5.jpg) ### Tooltips: 工具提示对象(Tooltips)就是当鼠标指针移到按钮或其它构件上并停留几秒时,弹出的文本串。 工具提示对象很容易使用。具体看下面的示例。 ~~~ /*File:tooltip.c *Date:2013-12-15 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> GtkTooltips *tooltips; int ch = 0; void callback(GtkWidget *widget,gpointer data) { //禁用已经激活的工具提示 if(ch){ gtk_tooltips_disable(tooltips); printf("0000\n"); ch = 0; }else{ ch = 1; printf("1111\n"); gtk_tooltips_enable(tooltips); } } int main(int argc, char*argv[]) { GtkWidget *window; GtkWidget *button; //初始化GTK gtk_init(&argc,&argv); //创建最上层主窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //连接信号"delete_event",使得窗口关闭时发生 g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); //设置窗口标题 gtk_window_set_title(GTK_WINDOW(window),"工具提示对象"); //设定窗口的默认宽高 //gtk_window_set_default_size(GTK_WINDOW(window),200,300); //设定窗口的位置,让窗口总在最前端 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //设定容器边框的宽度 gtk_container_set_border_width(GTK_CONTAINER(window),20); //创建按钮 button = gtk_button_new_with_label("关闭工具提示"); gtk_container_add(GTK_CONTAINER(window),button); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),NULL); gtk_widget_show(button); //创建工具提示 tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips,button,"这是一个工具提示按钮",NULL); gtk_tooltips_disable(tooltips); gtk_widget_show_all(window); gtk_main(); return FALSE; } ~~~ ### 进度条 Progress Bars 进度条用于显示正在进行的操作的状态。 ~~~ #include <gtk/gtk.h> typedef struct _ProgressData { GtkWidget *window; GtkWidget *pbar; int timer; gboolean activity_mode; }ProgressData; /* 更新进度条,这样就能够看到进度条的移动 */ gint progress_timeout( gpointer data ) { ProgressData *pdata =(ProgressData *)data; gdouble new_val; if (pdata->activity_mode) gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar)); else { /* 使用在调整对象中设置的取值范围计算进度条的值 */ new_val =gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01; if (new_val >1.0) new_val =0.0; /* 设置进度条的新值 */ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val); } /* 这是一个 timeout 函数,返回 TRUE,这样它就能够继续被调用 */ return TRUE; } /* 回调函数,切换在进度条你的滑槽上的文本显示 */ void toggle_show_text( GtkWidget *widget, ProgressData *pdata ) { const gchar *text; text =gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata->pbar)); if (text && *text) gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar), ""); else gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar), "some text"); } /* 回调函数,切换进度条的活动模式 */ void toggle_activity_mode( GtkWidget *widget, ProgressData *pdata ) { pdata->activity_mode = !pdata->activity_mode; if (pdata->activity_mode) gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar)); else /**/ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), 0.0); } /* 回调函数,切换进度条的移动方向 */ void toggle_orientation( GtkWidget *widget, ProgressData *pdata ) { /*获得滚动条的移动方向*/ switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata->pbar))) { case GTK_PROGRESS_LEFT_TO_RIGHT: /*设置滚动条移动方向*/ gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar), GTK_PROGRESS_RIGHT_TO_LEFT); break; case GTK_PROGRESS_RIGHT_TO_LEFT: gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar), GTK_PROGRESS_LEFT_TO_RIGHT); break; default: break; // 什么也不做 } } /* 清除分配的内存,删除定时器(timer) */ void destroy_progress( GtkWidget *widget,ProgressData *pdata) { gtk_timeout_remove (pdata->timer); pdata->timer =0; pdata->window =NULL; g_free (pdata); gtk_main_quit (); } int main( int argc,char *argv[]) { ProgressData *pdata; GtkWidget *align; GtkWidget *separator; GtkWidget *table; GtkWidget *button; GtkWidget *check; GtkWidget *vbox; gtk_init (&argc, &argv); /* 为传递到回调函数中的数据分配内存 */ pdata =g_malloc (sizeof (ProgressData)); pdata->window =gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE); g_signal_connect (G_OBJECT (pdata->window), "destroy",G_CALLBACK (destroy_progress),pdata); gtk_window_set_title (GTK_WINDOW (pdata->window), "进度条练习"); gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0); vbox =gtk_vbox_new (FALSE, 5); gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); gtk_container_add (GTK_CONTAINER (pdata->window), vbox); gtk_widget_show (vbox); /* 创建一个居中对齐的对象 */ align =gtk_alignment_new (0.5, 0.5, 0, 0); gtk_box_pack_start (GTK_BOX(vbox), align, FALSE, FALSE, 5); gtk_widget_show (align); /* 创建进度条 */ pdata->pbar =gtk_progress_bar_new (); gtk_container_add (GTK_CONTAINER (align), pdata->pbar); gtk_widget_show (pdata->pbar); /* 加一个定时器(timer),以更新进度条的值 */ pdata->timer =gtk_timeout_add (100, progress_timeout, pdata); separator =gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX(vbox), separator, FALSE, FALSE, 0); gtk_widget_show (separator); /* 行数、列数、同质性(homogeneous) */ table =gtk_table_new (2, 2, FALSE); gtk_box_pack_start (GTK_BOX(vbox), table, FALSE, TRUE, 0); gtk_widget_show (table); /* 添加一个复选按钮,以选择是否显示在滑槽里的文本 */ check =gtk_check_button_new_with_label ("Show text"); gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,GTK_EXPAND |GTK_FILL, GTK_EXPAND |GTK_FILL,5, 5); g_signal_connect (G_OBJECT (check), "clicked",G_CALLBACK (toggle_show_text),pdata); gtk_widget_show (check); /* 添加一个复选按钮,切换活动状态 */ check =gtk_check_button_new_with_label ("Activity mode"); gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,GTK_EXPAND |GTK_FILL, GTK_EXPAND |GTK_FILL,5, 5); g_signal_connect (G_OBJECT (check), "clicked",G_CALLBACK (toggle_activity_mode),pdata); gtk_widget_show (check); /* 添加一个复选按钮,切换移动方向 */ check =gtk_check_button_new_with_label ("Right to Left"); gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,GTK_EXPAND |GTK_FILL, GTK_EXPAND |GTK_FILL,5, 5); g_signal_connect (G_OBJECT (check), "clicked",G_CALLBACK (toggle_orientation),pdata); gtk_widget_show (check); /* 添加一个按钮,用来退出应用程序 */ button =gtk_button_new_with_label ("close"); g_signal_connect_swapped (G_OBJECT (button), "clicked",G_CALLBACK (gtk_widget_destroy),pdata->window); gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); /* 将按钮设置为能缺省的构件 */ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); /* 将缺省焦点设置到这个按钮上,使之成为缺省按钮,只要按回车键 * 就相当于点击了这个按钮 */ //译者注: 能缺省的构件在获取焦点后成为缺省构件,用户按方向键等可以切换焦点。 gtk_widget_grab_default (button); gtk_widget_show (button); gtk_widget_show (pdata->window); gtk_main (); return 0; } ~~~ 运行如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77979ae82.jpg) 参考 资料:   [http://guoyinghui2012.blog.163.com/blog/static/20871720020126294943228/](http://guoyinghui2012.blog.163.com/blog/static/20871720020126294943228/) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="范围控件(比例控件、滚动条控件)">范围控件(比例控件、滚动条控件)<a class="anchorjs-link " href="#范围控件(比例控件、滚动条控件)" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:58</span></p> <div id="md-view"> 这一章节介绍范围控件的一些基本函数的使用和实现,很多函数的细节,在GTK编程文档中有详细的介绍。我只是照抄了文档中的实例。当然生疏的部分自己也做了注释和理解。GTK文档链接在我的资源[里面可以下载](http://download.csdn.net/detail/jsh13417/6567043) ### 下面是范围控件的具体实例代码: ~~~ /*File:range_controls.c *Date:2013-12-08 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> /*范围控件: * 由一般按钮派生而来,只是开关按钮只有两个状态,通过点击 * 可以切换。 * 开关按钮是复选按钮和单选按钮的基础,所以单选按钮和复选按钮继承了 * 许多开关按钮的函数调用 */ GtkWidget *hscale,*vscale; void cb_pos_menu_select(GtkWidget *item,GtkPositionType pos) { /*设置两个比例构件的比例值的显示位置 *void gtk_scale_set_value_pos(GtkScale * scale,:比例构件 * GtkPositionType pos);:显示对象的位置 * GTK_POS_TOP * GTK_POS_RIGHT * GTK_POS_BOTTOM * GTK_POS_LEFT * */ printf("###%s,pos = %d \n",__func__,pos); gtk_scale_set_value_pos(GTK_SCALE(hscale),pos); gtk_scale_set_value_pos(GTK_SCALE(vscale),pos); } void cb_update_menu_select(GtkWidget *item,GtkUpdateType Policy) { /*设置两个比例控件的更新方式 *void gtk_range_set_update_policy(GtkRange *range,GtkUpdateType Policy); *range : 范围控件 *Policy :更新方式,有以下三个 * GTK_UPDATE_CONTINUOUS:信号时连续引发的 * GTK_UPDATE_DISCONTINUOUS:只有滑块停止移动,用户释放鼠标时才引发 * GTK_UPDATE_DELAYED:当用户释放鼠标,或者滑块短期停止移动时引发 * * */ gtk_range_set_update_policy(GTK_RANGE(hscale),Policy); gtk_range_set_update_policy(GTK_RANGE(vscale),Policy); } void cb_digits_scale(GtkAdjustment *adj) { /*设置 小数的位数 *gtk_scale_set_digits(GtkScale *scale,gint Digits) *参数:scale:比例构件对象 * Digits:要显示小数位数,最大13 * */ gtk_scale_set_digits(GTK_SCALE(hscale),(gint)adj->value); gtk_scale_set_digits(GTK_SCALE(vscale),(gint)adj->value); } void cb_page_size(GtkAdjustment * get,GtkAdjustment * set) { /*将实例调整对象的page_size,和page_increment size设置为“page Size” *比例控件指定的数值。 */ set->page_size = get->value; set->page_increment = get->value; /*设置调整对象的值并使它引发一个“changed"信号,以重新配置所有已连接到这个调整对象的构件 */ gtk_adjustment_set_value(set,CLAMP(set->value,set->lower,(set->upper-set->page_size))); } void cb_draw_value(GtkToggleButton * button) { /*根据复选框的状态设置在比例构件上是否显示比例值 *TRUE :显示 FALSE:不显示 * */ gtk_scale_set_draw_value(GTK_SCALE(hscale),button->active); gtk_scale_set_draw_value(GTK_SCALE(vscale),button->active); } GtkWidget * make_menu_item(gchar *name,GCallback callback,gpointer data) { GtkWidget *item; item = gtk_menu_item_new_with_label(name); g_signal_connect(G_OBJECT(item),"activate",callback,data); gtk_widget_show(item); return item; } /*设置比例控件默认方式*/ void scale_set_default_values(GtkScale * scale) { gtk_range_set_update_policy(GTK_RANGE(scale),GTK_UPDATE_CONTINUOUS); gtk_scale_set_digits(scale,1); gtk_scale_set_value_pos(scale,GTK_POS_TOP); gtk_scale_set_draw_value(scale,TRUE); } /*创建示例窗口*/ static void create_range_controls() { GtkWidget *window; GtkWidget *button; /*box1:纵向组装盒子 * */ GtkWidget *box1,*box2,*box3; GtkWidget *scrollbar; GtkWidget *separator; GtkWidget *opt,*menu,*item; GtkWidget *label; GtkWidget *scale; GtkWidget *adj1,*adj2; /************标准的窗口代码**********/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),20); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"范围控件练习"); /******************************/ /*创建一个纵向组装盒子*/ box1 = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); /*创建一个横向组装盒子*/ box2 = gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /*创建一个调整对象 * GtkObject *gtk_adjustment_new(gdouble value,调整对象的初始值,通常是最高或者最低位置 * gdouble lower,调整对象能取得的最低值 * gdouble upper,用于分栏构件最底部或最右边的坐标 * gdouble step_increment,小步调整的值 * gdouble page_increment,大步调整的值 * gdouble page_size);分栏构件的可视区域 * */ adj1 = gtk_adjustment_new(0.0,0.0,101.0,0.1,1.0,1.0); /*创建一个垂直比例控件*/ vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj1)); scale_set_default_values(GTK_SCALE(vscale)); gtk_box_pack_start(GTK_BOX(box2),vscale,TRUE,TRUE,0); gtk_widget_show(vscale); /*创建一个纵向组装盒子,并加入2个水平比例控件*/ box3 = gtk_vbox_new(FALSE,10); gtk_box_pack_start(GTK_BOX(box2),box3,TRUE,TRUE,0); gtk_widget_show(box3); /*创建一个水平比例控件*/ hscale = gtk_hscale_new(GTK_ADJUSTMENT(adj1)); /*设置控件的宽度和高度*/ gtk_widget_set_size_request(GTK_WIDGET(hscale),200,-1); scale_set_default_values(GTK_SCALE(hscale)); gtk_box_pack_start(GTK_BOX(box3),hscale,TRUE,TRUE,0); gtk_widget_show(hscale); /*创建一个滑动条*/ scrollbar = gtk_hscrollbar_new(GTK_ADJUSTMENT(adj1)); /*注意: * 这导致当滚动条移动时,比例构件总是连续更新 * */ gtk_range_set_update_policy(GTK_RANGE(scrollbar),GTK_UPDATE_CONTINUOUS); gtk_box_pack_start(GTK_BOX(box3),scrollbar,TRUE,TRUE,0); gtk_widget_show(scrollbar); box2 = gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /*用一个复选框控制是否显示比较构件的当前的数值*/ button = gtk_check_button_new_with_label("Display value on scale widgets"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE); g_signal_connect(G_OBJECT(button),"toggled",G_CALLBACK(cb_draw_value),NULL); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); box2 = gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); /*用一个选项菜单以改变显示值的位置*/ label = gtk_label_new("Scale Value Position"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); opt = gtk_option_menu_new(); menu = gtk_menu_new(); item = make_menu_item("TOP",G_CALLBACK(cb_pos_menu_select),GINT_TO_POINTER(GTK_POS_TOP)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item = make_menu_item("BUTTOM",G_CALLBACK(cb_pos_menu_select),GINT_TO_POINTER(GTK_POS_BOTTOM)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item = make_menu_item("RIGHT",G_CALLBACK(cb_pos_menu_select),GINT_TO_POINTER(GTK_POS_RIGHT)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item = make_menu_item("LEFT",G_CALLBACK(cb_pos_menu_select),GINT_TO_POINTER(GTK_POS_LEFT)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); gtk_option_menu_set_menu(GTK_OPTION_MENU(opt),menu); gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0); gtk_widget_show(opt); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); box2 = gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),0); /*设置比例构件的更新方式*/ label = gtk_label_new("Scale Update Policy:"); gtk_box_pack_start(GTK_BOX(box2),label,TRUE,TRUE,0); gtk_widget_show(label); opt = gtk_option_menu_new(); menu = gtk_menu_new(); item = make_menu_item("Continuous",G_CALLBACK(cb_update_menu_select),GINT_TO_POINTER(GTK_UPDATE_CONTINUOUS)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item = make_menu_item("Discontinuous",G_CALLBACK(cb_update_menu_select),GINT_TO_POINTER(GTK_UPDATE_DISCONTINUOUS)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item = make_menu_item("Delayed",G_CALLBACK(cb_update_menu_select),GINT_TO_POINTER(GTK_UPDATE_DELAYED)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); gtk_option_menu_set_menu(GTK_OPTION_MENU(opt),menu); gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0); gtk_widget_show(opt); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); box2 = gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); /*用于调整比例构件小数位数*/ label = gtk_label_new("Scale Digits:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); adj2 = gtk_adjustment_new(1.0,0.0,5.0,1.0,1.0,0.0); g_signal_connect(G_OBJECT(adj2),"value_changed",G_CALLBACK(cb_digits_scale),NULL); scale = gtk_hscale_new(GTK_ADJUSTMENT(adj2)); gtk_scale_set_digits(GTK_SCALE(scale),0); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); box2 = gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); /*用于调整水平比例构件滚动条的page size */ label = gtk_label_new("Scrollbar Page Size:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); adj2 = gtk_adjustment_new(1.0,1.0,110.0,1.0,1.0,0.0); g_signal_connect(G_OBJECT(adj2),"value_changed",G_CALLBACK(cb_page_size),adj1); scale = gtk_hscale_new(GTK_ADJUSTMENT(adj2)); gtk_scale_set_digits(GTK_SCALE(scale),0); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /*创建一个分割线*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,0); gtk_widget_show(separator); box2 = gtk_vbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,0); gtk_widget_show(box2); /*创建一个退出按钮*/ button = gtk_button_new_with_label("Quit"); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_main_quit),NULL); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); /*将退出按钮固定为缺省,只要按回车键就能触发*/ GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); gtk_widget_show(window); } int main(int argc,char *argv[]) { gtk_init(&argc,&argv); /*创建范围控件*/ create_range_controls(); gtk_main(); return 0; } ~~~ 执行后: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77974917b.jpg) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="按钮构件">按钮构件<a class="anchorjs-link " href="#按钮构件" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:56</span></p> <div id="md-view"> 创建按钮有好几种方法。你可以用 gtk_button_new_with_label() 或 gtk_button_new_with_mnemonic() 来创建一个带标签的按钮,用 gtk_button_new_from_stock() 来从一个原料(stock)项创建一个包含图像和文本的按钮,或者用 gtk_button_new() 创建一个空白按钮。接着你可以决定把一个标签或位图(pixmap)组装到这个新创建的按钮里。要这样做,创建一个新的盒,然后用常见的 gtk_box_pack_start() 把你的对象组装到盒里,再gtk_container_add() 把盒组装到按钮里。 ### 下面是演示用函数gtk_button_new()去创建一个带图像和标签的按钮控件。 ~~~ /*File:Normal_Button.c *Date:2013-12-03 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> /*创建一个横向盒,它包含一个图像和一个标签,并非你会这个盒子*/ GtkWidget *xpm_label_box(gchar *xpm_filename,gchar *label_text) { GtkWidget *box; GtkWidget *label; GtkWidget *image; /*为图像和标签创建盒*/ box = gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(box),2); /*创建一个图像*/ image = gtk_image_new_from_file(xpm_filename); /*为按钮创建一个标签*/ label = gtk_label_new(label_text); /*图像和按钮组装到盒子里*/ gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,3); gtk_box_pack_start(GTK_BOX(box),label,FALSE,FALSE,3); gtk_widget_show(image); gtk_widget_show(label); return box; } /*回调函数 *传到这个函数的数据将呗打印到标准输出 * */ void callback(GtkWidget *widget, gpointer data) { g_print("Hello again -%s was pressed\n",(char *) data); } /*退出回调函数*/ gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box; /*初始化*/ gtk_init(&argc,&argv); /*创建窗口*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),80); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"普通按钮练习"); button = gtk_button_new(); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),(gpointer)"cool button"); box = xpm_label_box("info.xpm","cool button"); gtk_widget_show(box); gtk_container_add(GTK_CONTAINER(button),box); gtk_widget_show(button); gtk_container_add(GTK_CONTAINER(window),button); gtk_widget_show(window); gtk_main(); return 0; } ~~~ 运行程序显示下面的图像: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77970a13f.jpg) ### 按钮构件有如下信号: • pressed --- 当鼠标键在按钮构件里按下时发出 • released --- 当鼠标键在按钮构件里释放时发出 • clicked --- 当鼠标键在按钮构件里按下并接着在按钮构件里释放时发出 • enter --- 当鼠标光标进入按钮构件时发出 • leave --- 当鼠标光标离开按钮构件时发出 ### 开关、复选按钮 ### ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77971d771.jpg) ~~~ /*File:Toggle_button.c *Date:2013-12-07 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> /*开关按钮: * 由一般按钮派生而来,只是开关按钮只有两个状态,通过点击 * 可以切换。 * 开关按钮是复选按钮和单选按钮的基础,所以单选按钮和复选按钮继承了 * 许多开关按钮的函数调用 */ GtkWidget *button1; GtkWidget *button2; /*回调函数 *传到这个函数的数据将呗打印到标准输出 * */ void Toggle_Button_callback(GtkWidget *widget, gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){ g_print(" 按钮被按下\n"); }else{ g_print("按钮是弹起的\n",(char *) data); } } void callback(GtkWidget *widget, gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button1))){ g_print(" 数学被选中\n"); }else{ g_print("nothing\n"); } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button2))){ g_print(" 语文被选中\n"); }else{ g_print("nothing\n"); } } /*退出回调函数*/ gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box; /*初始化*/ gtk_init(&argc,&argv); /*创建窗口*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),20); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"开关按钮练习"); /*创建一个组装盒子*/ box = gtk_vbox_new(FALSE,0); /*设置一个开关按钮*/ button = gtk_toggle_button_new_with_label("打开"); /*设置按钮的状态,默认为弹起 FALSE .*/ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),FALSE); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(Toggle_Button_callback),(gpointer)"cool button"); gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,0); gtk_widget_show(button); /*********设置复选按钮********/ button1 = gtk_check_button_new_with_label("数学"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button1),TRUE); gtk_box_pack_start(GTK_BOX(box),button1,TRUE,TRUE,0); gtk_widget_show(button1); button2 = gtk_check_button_new_with_label("语文"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button2),TRUE); gtk_box_pack_start(GTK_BOX(box),button2,TRUE,TRUE,0); gtk_widget_show(button2); button = gtk_button_new_with_label("OK"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE); gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,0); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),NULL); gtk_widget_show(button); gtk_container_add(GTK_CONTAINER(window),box); gtk_widget_show(box); gtk_widget_show(window); gtk_main(); return 0; } ~~~ ###  单选按钮  ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779732832.jpg) ###   ~~~ /*File:Radio_Button.c *Date:2013-12-03 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> /*创建单选按钮,点击close 回输出那个单选按钮被点击 * 单选按钮是分组的,一个组中只能有一个对象被选中、按下 *当应用程序中,要从多个选项中选中一个时用到 */ enum Subject{ SHUXVE, YUWEN, YINGYU }; GtkWidget *button1;//语文 GtkWidget *button2;//数学 GtkWidget *button3;//英语 void Radio_Button_callback(GtkWidget *widget,gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button1))){ g_print("语文被点击\n"); } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button2))){ g_print("数学被点击\n"); } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button3))){ g_print("英语被点击\n"); } } /*回调函数 *传到这个函数的数据将呗打印到标准输出 * */ void callback(GtkWidget *widget, gpointer data) { g_print("Hello again -%s was pressed\n",(char *) data); } /*退出回调函数*/ gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *separator; GSList *group; /*初始化*/ gtk_init(&argc,&argv); /*创建窗口*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),0); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"单选按钮练习"); box1 = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); box2 = gtk_vbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); button1 = gtk_radio_button_new_with_label(NULL,"语文"); gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,0); gtk_widget_show(button1); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button1)); button2 = gtk_radio_button_new_with_label(group,"数学"); /*默认是选择这个*/ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button2),TRUE); gtk_box_pack_start(GTK_BOX(box2),button2,TRUE,TRUE,0); gtk_widget_show(button2); button3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(button2),"英语"); gtk_box_pack_start(GTK_BOX(box2),button3,TRUE,TRUE,0); gtk_widget_show(button3); /*分割线*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,0); gtk_widget_show(separator); box2 = gtk_vbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,0); gtk_widget_show(box2); /*退出按钮*/ button = gtk_button_new_with_label("close"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(Radio_Button_callback),(gpointer)"cool button"); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); gtk_widget_show(window); gtk_main(); return 0; } ~~~ </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="组装盒,表组装">组装盒,表组装<a class="anchorjs-link " href="#组装盒,表组装" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:54</span></p> <div id="md-view"> ### 构件概述 在GTK中创建一个构件的一般步骤: 1、gtk_*_new():创建各种构件的函数 2、把所有相连接的信号都连接到对应的信号处理函数 3、设定构件的属性 4、用gtk_container_add() or grk_box_pack_start()等适当的函数把构件放置到一个控件中, 5、gtk_widget_show()显示构件。      ### 组装构件 多 数组装是通过创建一些“盒(boxes)”来达成的,这是些不可见的构件容器,它们有两种形式:一种是横向盒(horizontal box),一种是纵向盒(vertical box)。当我们组装构件到横向盒里时,这些构件就依着我们调用的顺序由左至右或从右到左水平地插入进去。在纵向盒里,则从顶部到底部或相反地组装构件, 你可以使用任意的盒组合,比如盒套盒或者盒挨着盒,用以产生你想要的效果。 要创建一个新的横向盒我们调用 gtk_hbox_new(),对于纵向盒,用 gtk_vbox_new()。gtk_box_pack_start() 和 gtk_box_pack_end() 函数用来将对象组装到这些容器中。gtk_box_pack_start() 将对象从上到下组装到纵向盒中,或者从左到右组装到横向盒中。gtk_box_pack_end() 则相反,从下到上组装到纵向盒中,或者从右到左组装到横向盒中。使用这些函数允许我们调整自己的构件向左或向右对齐,同时也可以混入一些其它的方法来达到 我们想要的设计效果。在我们的示例中多数使用gtk_box_pack_start()。被组装的对象可以是另一个容器或构件。事实上,许多构件本身就是容器,包括按钮,只不过我们通常在按钮中只放 入一个标签。看下面的具体例子: ~~~ /*File:packbox.c *Date:2013-11-17 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data) { gtk_main_quit(); return FALSE; } /*生成一个填满按钮-标签的横向盒,我们将感兴趣的参数传递进这个函数 * 我们不显示这个盒子,但显示它内部的所有东西 */ GtkWidget * make_box(gboolean homogeneous,gint spacing,gboolean expand,gboolean fill,guint padding) { GtkWidget *box; GtkWidget *button; char padstr[80]; /*homogeneous:确定所有控件的大小 * TRUE:表示组装和计算最大控件的大小,然后其他控件按照最大控件的大小分配 * FALSE:建立不同大小的控件,以各自内容。 * spacing:用它来确定插入组装和的构件之间的空间。 * 0:表示空间之间不留空间 * */ box = gtk_hbox_new (homogeneous,spacing); button = gtk_button_new_with_label("gtk_box_pack"); gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); button = gtk_button_new_with_label("box,"); gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); button = gtk_button_new_with_label("button"); gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); if(expand == TRUE){ button = gtk_button_new_with_label("TRUE,"); } else { button = gtk_button_new_with_label("FALSE,"); } gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); button = gtk_button_new_with_label(fill?"TRUE":"FALSE"); gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); sprintf(padstr,"%d);",padding); button = gtk_button_new_with_label(padstr); gtk_box_pack_start(GTK_BOX(box),button,expand,fill,padding); gtk_widget_show(button); return box; } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *separator; GtkWidget *label; GtkWidget *quitbox; int which; /*初始化*/ gtk_init(&argc,&argv); if(argc != 2){ fprintf(stderr,"usage:packbox num ,where num is 1,2,3\n"); exit(1); } which = atoi(argv[1]); /*创建窗口*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),80); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"组装盒练习"); /* 我们创建一个纵向盒(vbox)把横向和组装进来 *这样我们可以将填满按钮的很想和一个个的堆叠到这个纵向盒子里 */ box1 = gtk_vbox_new(FALSE,0); /**/ switch(which){ case 1: /*创建一个标签*/ label = gtk_label_new("gtk_hbox_new(FALSE,0);"); /*使标签靠左排列*/ gtk_misc_set_alignment(GTK_MISC(label),0,0); /*将标签组装到纵向盒中*/ gtk_box_pack_start(GTK_BOX(box1),label,FALSE,FALSE,0); /*显示标签*/ gtk_widget_show(label); /*调用我们生成盒的函数-homogeneous = FALSE,spacing = 0 * * expand = FALSE,fill = FALSE,padding = 0 */ box2 = make_box(TRUE,0,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*调用我们生成盒的函数-homogeneous = FALSE,spacing = 0 * * expand = TRUE,fill = FALSE,padding = 0 */ box2 = make_box(FALSE,0,TRUE,FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*调用我们生成盒的函数-homogeneous = FALSE,spacing = 0 * * expand = TRUE,fill = TRUE,padding = 0 */ box2 = make_box(FALSE,0,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*创建一个分割线,并组装到纵向盒*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,5); gtk_widget_show(separator); /*创建一个新的标签,并显示它*/ label = gtk_label_new("gtk_hbox_new(TRUE,0);"); gtk_misc_set_alignment(GTK_MISC(label),0,0); gtk_box_pack_start(GTK_BOX(box1),label,FALSE,FALSE,0); gtk_widget_show(label); box2 = make_box(TRUE,0,TRUE,FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); box2 = make_box(FALSE,0,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*创建一个分割线,并组装到纵向盒*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,5); gtk_widget_show(separator); break; case 2: /*创建一个新的标签,并显示它*/ label = gtk_label_new("gtk_hbox_new(FALSE,10);"); gtk_misc_set_alignment(GTK_MISC(label),0,0); gtk_box_pack_start(GTK_BOX(box1),label,FALSE,FALSE,0); gtk_widget_show(label); box2 = make_box(FALSE,10,TRUE,FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); box2 = make_box(FALSE,10,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*创建一个分割线,并组装到纵向盒*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,5); gtk_widget_show(separator); /*创建一个新的标签,并显示它*/ label = gtk_label_new("gtk_hbox_new(FALSE,0);"); gtk_misc_set_alignment(GTK_MISC(label),0,0); gtk_box_pack_start(GTK_BOX(box1),label,FALSE,FALSE,0); gtk_widget_show(label); box2 = make_box(FALSE,0,TRUE,FALSE,10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); box2 = make_box(FALSE,0,TRUE,TRUE,10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*创建一个分割线,并组装到纵向盒*/ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,5); gtk_widget_show(separator); break; case 3: /*示范gtk_box_pack_end()右对齐构件的能力*/ box2 = make_box(FALSE,0,FALSE,FALSE,0); /*创建放在末端的标签*/ label = gtk_label_new("end"); gtk_box_pack_end(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); /*放在底部的分割线*/ separator = gtk_hseparator_new(); gtk_widget_set_size_request(separator,400,5); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,5); gtk_widget_show(separator); break; default: break; } /*创建一个新的横向盒,用来推出按钮*/ quitbox = gtk_hbox_new(FALSE,0); button = gtk_button_new_with_label("退出"); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(delete_event),window); gtk_box_pack_start(GTK_BOX(quitbox),button,TRUE,FALSE,0); gtk_box_pack_start(GTK_BOX(box1),quitbox,TRUE,FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(button); gtk_widget_show(quitbox); gtk_widget_show(box1); gtk_widget_show(window); gtk_main(); return 0; }; ~~~ ### 下面是执行程序的结果显示: ### 1、情况显示 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7796a783f.jpg) ### 2、情况显示 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7796bf4f5.jpg) ### 3、情况显示  ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7796d3e3b.jpg) ### 表组装: ~~~ /*File:tableBox.c *Date:2013-11-27 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> #include <stdlib.h> /*回调函数 *传到这个函数的数据将呗打印到标准输出 * */ void callback(GtkWidget *widget, gpointer data) { g_print("Hello again -%s was pressed\n",(char *) data); } /*退出回调函数*/ gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data) { gtk_main_quit(); return FALSE; } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *table; /*初始化*/ gtk_init(&argc,&argv); /*创建窗口*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*这个一般必要有delete_event信号到主窗口*/ g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); /*设置窗口宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),80); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"表组装练习"); /* 创建一个2X2的表 *GtkWidget *gtk_table_new(guint rows,guint columns,gboolean homogeneous); *rows:表中要安排的行数 *columns:表中要安排的列数 *homogeneous:TRUE标示表格框的大小都将调整为表中最大构件的大小。 * FALSE每个表格框将会按照同行中最高的构件,与同列中最宽的构件来决定自身的大小 * */ table = gtk_table_new(2,2,TRUE); /*将表放进主窗口*/ gtk_container_add(GTK_CONTAINER(window),table); /*创建一个按钮*/ button = gtk_button_new_with_label("love you!"); /*将按钮设置回调函数*/ g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),(gpointer)"I love you songsong!"); /*将button插入表的左上象限 *void gtk_table_attach(GtkTable *table,已经创建的表 *GtkWidget *child,想放进表里的构件 *guint left_attach,构件的放置位置 *guint right_attach, *guint top_attach, *guint bottom_attach, *GtkAttachOptions xoptions,下面是用来指定组装时的选项GTK_FILL:构件会扩展以是用所有可用空间 *GtkAttachOptions yoptions,GTK_SHRINK:构件会和表一个缩小 GTK_EXPAND: *guint xpadding,下面2个padding,构件周围的空白区域 *guint ypadding); *这里有个简写的函数 *void gtk_table_attach_defaults(); *默认缺省参数options:GTK_FILL|GTK_EXPAND padding:为0; * * */ gtk_table_attach_defaults(GTK_TABLE(table),button,0,1,0,1); gtk_widget_show(button); /*创建第二个按钮*/ button = gtk_button_new_with_label("miss you!"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),(gpointer)"I miss you songsong!"); gtk_table_attach_defaults(GTK_TABLE(table),button,1,2,0,1); gtk_widget_show(button); /*创建quit按钮*/ button = gtk_button_new_with_label("quit"); g_signal_connect(G_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; } ~~~ 运行如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd7796ea9a9.jpg) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="入门篇(helloworld)">入门篇(helloworld)<a class="anchorjs-link " href="#入门篇(helloworld)" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:51</span></p> <div id="md-view"> ### 下面来介绍GTK编程入门,你的第一个程序hellowoeld。直接通过程序来讲解吧。 ~~~ /*File:helloworld.c *Date:2013-11-23 *Author:sjin *Mail:413977243@qq.com */ /*my first test program*/ #include <gtk/gtk.h> /* 这是一个回调函数。data 参数在本示例中被忽略。 * 后面有更多的回调函数示例。*/ void hello( GtkWidget *widget,gpointer data ) { g_print ("Hello World\n"); } gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) { /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 * 返回 TRUE,你不希望关闭窗口。 * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 为 FALSE 程序会关闭,关闭时调用destroy()。*/ return TRUE; } /* 另一个回调函数 */ void destroy( GtkWidget *widget,gpointer data ) { gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是构件的存储类型 */ GtkWidget *window; GtkWidget *button; /* 这个函数在所有的 GTK 程序都要调用。参数由命令行中解析出来并且送到该程序中*/ gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"My first program helloworld!"); /* 当窗口收到 "delete_event" 信号 (这个信号由窗口管理器发出,通常是“关闭” * 选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的 delete_event() 函数。 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* 在这里我们连接 "destroy" 事件到一个信号处理函数。 * 对这个窗口调用 gtk_widget_destroy() 函数或在 "delete_event" 回调函数中返回 FALSE 值 * 都会触发这个事件。*/ g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); /* 设置窗口边框的宽度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 150); /* 创建一个标签为 "Hello World" 的新按钮。*/ button = gtk_button_new_with_label ("Hello World"); /* 当按钮收到 "clicked" 信号时会调用 hello() 函数,并将NULL传给 * 它作为参数。hello() 函数在前面定义了。*/ g_signal_connect (G_OBJECT (button), "clicked",G_CALLBACK (hello), NULL); /* 当点击按钮时,会通过调用 gtk_widget_destroy(window) 来关闭窗口。 * "destroy" 信号会从这里或从窗口管理器发出。*/ g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy),window); /* 把按钮放入窗口 (一个 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (window), button); /* 最后一步是显示新创建的按钮和窗口 */ gtk_widget_show (button); gtk_widget_show (window); /* 所有的 GTK 程序必须有一个 gtk_main() 函数。程序运行停在这里 * 等待事件 (如键盘事件或鼠标事件) 的发生。*/ gtk_main (); return 0; } ~~~ 编译 gcc test.c `pkg-config --cflags --libs gtk+-2.0`(以后编译都参照这个样子,以后将不再具体说明) 运行程序将出现下面的窗口,单击button窗口将被关闭 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77967dd88.jpg) 下面是改进版的helloworld ~~~ /*File:helloworld2.c *Date:2013-11-17 *Author:sjin *Mail:413977243@qq.com */ #include <gtk/gtk.h> /*改进的回调函数,传递到该函数的数据将会被打印到标准输出*/ void callback(GtkWidget *widget,gpointer data) { g_print("Hello again-%s was pressed\n",(gchar*) data); } /*关闭窗口的函数*/ void destroy(GtkWidget *widget,gpointer data) { g_print("退出hello world!\n"); gtk_main_quit(); } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box1; /*函数gtk_init()会在每个GTK的应用程序中调用。 * 该函数设定默认的视频和颜色默认参数,接下来会调用函数 * gdk_init()该函数初始化要使用的库,设定默认的信号处理 *检查传递到程序的命令行参数 * */ gtk_init(&argc,&argv); //下面两行创建并显示窗口。创建一个200*200的窗口。 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*设置窗口标题*/ gtk_window_set_title(GTK_WINDOW(window),"Helloworld2.c test!"); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(destroy),NULL); /*设置窗口边框的宽度*/ gtk_container_set_border_width(GTK_CONTAINER(window),80); /*创建一个组装盒 *我们看不见它,用来排列构建的工具 * */ box1 = gtk_hbox_new(FALSE,0); /*把组装盒box1放到主窗口中*/ gtk_container_add(GTK_CONTAINER(window),box1); /*创建一个标签为“欢迎”的按钮*/ button = gtk_button_new_with_label("欢迎"); /*当按下欢迎按钮时,我们调用 callback函数,会打印出我们传递的参数*/ g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),"欢迎大家来到我的博客学习!"); /*我们将button 按钮放入组装盒中*/ gtk_box_pack_start(GTK_BOX(box1),button,TRUE,TRUE,0); /*欢迎按钮设置成功,别忘了写下个函数来显示它*/ gtk_widget_show(button); /*创建第二个按钮*/ button = gtk_button_new_with_label("说明"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback),"GTK编程入门学习!"); gtk_box_pack_start(GTK_BOX(box1),button,TRUE,TRUE,0); gtk_widget_show(button); /*创建一个退出按钮*/ button = gtk_button_new_with_label("退出"); /*当点击退出按钮时,会触发gtk_widet_destroy来关闭窗口,destroy信号从这里发出 * 会触发destroy函数。*/ g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),window); gtk_box_pack_start(GTK_BOX(box1),button,TRUE,TRUE,0); gtk_widget_show(button); gtk_widget_show(box1); gtk_widget_show(window); //进入主循环 gtk_main(); return 0; } ~~~ ### 运行程序,会弹出下面的窗口 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd77969010e.jpg) ### 依次点击欢迎、说明、退出按钮,会打印下面的信息 ~~~ Hello again-欢迎大家来到我的博客学习! was pressed Hello again-GTK编程入门学习! was pressed 退出hello world! ~~~ 退出方式有2种,一种是点击窗口上的关闭窗,另一种就是点击按钮退出 参考资料: [http://download.csdn.net/detail/jsh13417/6567043](http://download.csdn.net/detail/jsh13417/6567043) [GTK+2.0 中的容器控件与布局技巧](http://www.ibm.com/developerworks/cn/linux/l-gtk/part1/index.html) [GTK+中的插件](http://www.ibm.com/developerworks/cn/linux/l-gtkplgin/index.html) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="Ubuntu下安装GTK的三种方法">Ubuntu下安装GTK的三种方法<a class="anchorjs-link " href="#Ubuntu下安装GTK的三种方法" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:49</span></p> <div id="md-view"> 1 安装命令: sudo apt-get install gnome-core-devel  sudo apt-get install libglib2.0-doc libgtk2.0-doc  sudo apt-get install devhelp  sudo apt-get install glade-gnome glade-common glade-doc   安装GTK环境只要安装一个gnome-core-devel就可以了,里面集成了很多其他的包。除此之外还要转一些其 他的东西,如libglib2.0 -doc、libgtk2.0-doc帮助文档,devhelp帮助文档查看,glade-gnome、glade- common、glade-doc图形界面设计等。 使用外部命令查看安装的gtk库版 $pkg-config --modversion gtk+ (查看1.2.x版本) $pkg-config --modversion gtk+-2.0 (查看 2.x 版本) $pkg-config --version (查看pkg-config的版本) $pkg-config --list-all grep gtk (查看是否安装了gtk) 安装gtk2.0 sudo apt-get install libgtk2.0-dev 2  Ubuntu下GTK的安装  apt-get install build-essential #这将安装gcc/g++/gdb/make 等基本编程工具 apt-get install gnome-core-devel #这将安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件 apt-get install pkg-config #用于在编译GTK程序时自动找出头文件及库文件位置  apt-get install devhelp #这将安装 devhelp GTK文档查看程序 apt-get install libglib2.0-doc libgtk2.0-doc #这将安装 gtk/glib 的API参考手册及其它帮助文档 apt-get install glade libglade2-dev #这将安装基于GTK的界面GTK是开发Gnome窗口的c/c++语言图形库 apt-get install libgtk2.0*, gtk+2.0所需的所有文件统通下载安装完毕。 应用程序编译命令:gcc test.c `pkg-config --cflags --libs gtk+-2.0`,编译通过,运行正常。  pkg-config是一个用来管理包的程序,在控制台输入 pkg-config --cflags --libs gtk+-2.0,可以发现 输出的文本包括了gcc编译gtk+2.0所需要的所有选项(头文件目录和库文件)。  这里有一点需要注意, gcc test.c `pkg-config --cflags --libs gtk+-2.0`, pkg-config --cflags - -libs gtk+-2.0两侧的引号并不是真正的引号,而是键盘数字件那一行,最左边的那个字符。如果错用了 单引号,gcc无法使用 pkg-config --cflags --libs gtk+-2.0产生的文本作为编译选项。构造程序。 3  GTK的安装  apt-get install build-essential #这将安装gcc/g++/gdb/make 等基本编程工具 apt-get install gnome-core-devel #这将安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件 apt-get install pkg-config #用于在编译GTK程序时自动找出头文件及库文件位置 apt-get install devhelp #这将安装 devhelp GTK文档查看程序 apt-get install libglib2.0-doc libgtk2.0-doc #这将安装 gtk/glib 的API参考手册及其它帮助文档 apt-get install glade libglade2-dev #这将安装基于GTK的界面GTK是开发Gnome窗口的c/c++语言图形库 apt-get install libgtk2.0*, gtk+2.0所需的所有文件统通下载安装完毕。 应用程序编译命令:gcc test.c `pkg-config --cflags --libs gtk+-2.0`,编译通过,运行正常。  pkg-config是一个用来管理包的程序,在控制台输入 pkg-config --cflags --libs gtk+-2.0,可以发 现输出的文本包括了gcc编译gtk+2.0所需要的所有选项(头文件目录和库文件)。  这里有一点需要注意, gcc test.c `pkg-config --cflags --libs gtk+-2.0`, pkg-config --cflags --libs gtk+-2.0两侧的引号并不是真正的引号,而是键盘数字件那一行,最左边的那个字符。如果错用了 单引号,gcc无法使用 pkg-config --cflags --libs gtk+-2.0产生的文本作为编译选项。构造程序。 ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× 一个简单的测试程序: ~~~ /*File:gtk_test.c *Date:2013-11-17 *Author:sjin *Mail:413977243@qq.com */ #include <stdio.h> #include <gtk/gtk.h> int main(int argc,char *argv[]) { GtkWidget *window; /*函数gtk_init()会在每个GTK的应用程序中调用。 * 该函数设定默认的视频和颜色默认参数,接下来会调用函数 * gdk_init()该函数初始化要使用的库,设定默认的信号处理 *检查传递到程序的命令行参数 * */ gtk_init(&argc,&argv); //下面两行创建并显示窗口。创建一个200*200的窗口。 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_show(window); //进入主循环 gtk_main(); return 0; } ~~~ 编译上面的程序 gcc test.c `pkg-config --cflags --libs gtk+-2.0`。如果编译通过说明环境安装成功。 运行./a.out 会弹出下面的界面 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-24_57bd779667bea.jpg) </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> <section class="normal markdown-section"> <h1 id="前言">前言<a class="anchorjs-link " href="#前言" data-anchorjs-icon=""></a></h1> <p><span class="sa-last-update-time">最后更新于:2022-04-01 20:21:47</span></p> <div id="md-view"> > 原文出处:[GTK编程基础学习](http://blog.csdn.net/column/details/sjin-gtk.html) 作者:[sjin_1314](http://blog.csdn.net/sjin_1314) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # GTK编程基础学习 > GTK+(GIMP Toolkit)是一套源码以LGPL许可协议分发、跨平台的图形工具包。最初是为GIMP写的,已成为一个功能强大、设计灵活的一个通用图形库,本专栏是参照GTK教程中的实例,自己亲自敲写代码尝试,并附上个人的一些见解。 </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/marked.min.js"></script> <script>content=document.getElementById("md-view").innerHTML;</script>'; <script>document.getElementById("md-view").innerHTML = marked.parse(content)</script> </section> </div> </div> <div class="banquan"> </div> </div> <a href="" rel="nofollow" class="navigation navigation-prev" id="shangyige"> <i class="fa fa-angle-left"></i> </a> <a href="" rel="nofollow" class="navigation navigation-next" id="xiayige"> <i class="fa fa-angle-right"></i> </a> </div> </div> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/js.js"></script> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/ciambook.js"></script> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/theme.js"></script> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/bootstrap.js"></script> <script src="https://docs.gechiui.com/digest-sjin-gtk/gc-content/themes/gechiui-book/js/fontsettings.js"></script> </body> </html>