GTK+ 组件 II
最后修改于 2023 年 10 月 18 日
在本 GTK+ 编程教程中,我们将继续介绍各种 GTK+ 组件。
GktComboBoxText
GktComboBoxText
是一个允许用户从选项列表中选择的组件。选项是字符串。
#include <gtk/gtk.h> void combo_selected(GtkWidget *widget, gpointer window) { gchar *text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)); gtk_label_set_text(GTK_LABEL(window), text); g_free(text); } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *combo; GtkWidget *label; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GtkComboBox"); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window), 15); gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); hbox = gtk_hbox_new(FALSE, 0); vbox = gtk_vbox_new(FALSE, 15); combo = gtk_combo_box_new_text(); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu"); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Arch"); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Fedora"); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Mint"); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Gentoo"); gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Debian"); gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0); label = gtk_label_new("..."); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(window), hbox); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(combo_selected), (gpointer) label); gtk_widget_show_all(window); gtk_main(); return 0; }
该示例显示了一个组合框和一个标签。组合框有六个选项的列表。这些是 Linux 发行版的名称。标签组件显示从组合框中选择的选项。
combo = gtk_combo_box_text_new();
gtk_combo_box_text_new
函数创建一个仅包含文本的简单组合框。
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu");
gtk_combo_box_text_append_text
函数将一个字符串追加到存储在组合框中的字符串列表中。
label = gtk_label_new("-");
创建一个新的标签组件。
gchar *text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)); gtk_label_set_text(GTK_LABEL(window), text); g_free(text);
我们获取选定的文本并将其设置为标签文本。gtk_combo_box_get_active_text
函数返回组合框中当前活动的字符串。我们使用 gtk_label_set_text
函数将字符串设置为标签。

GtkHSeparator
GtkHSeparator
是一个水平分隔符。它是一种装饰组件。还有一个姐妹组件 GtkVSeparator
。
#include <gtk/gtk.h> int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *label1; GtkWidget *label2; GtkWidget *hseparator; GtkWidget *vbox; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(window), "GtkHSeparator"); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(window), 10); label1 = gtk_label_new("Zinc is a moderately reactive, blue gray metal \ that tarnishes in moist air and burns in air with a bright bluish-green flame,\ giving off fumes of zinc oxide. It reacts with acids, alkalis and other non-metals.\ If not completely pure, zinc reacts with dilute acids to release hydrogen."); gtk_label_set_line_wrap(GTK_LABEL(label1), TRUE); label2 = gtk_label_new("Copper is an essential trace nutrient to all high \ plants and animals. In animals, including humans, it is found primarily in \ the bloodstream, as a co-factor in various enzymes, and in copper-based pigments. \ However, in sufficient amounts, copper can be poisonous and even fatal to organisms."); gtk_label_set_line_wrap(GTK_LABEL(label2), TRUE); vbox = gtk_vbox_new(FALSE, 10); gtk_container_add(GTK_CONTAINER(window), vbox); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), label1, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hseparator, FALSE, TRUE, 10); gtk_box_pack_start(GTK_BOX(vbox), label2, FALSE, TRUE, 0); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window); gtk_main(); return 0; }
代码示例显示了两个化学元素的定义;它们由水平分隔符分隔。这使得该示例更具视觉吸引力。
label1 = gtk_label_new("Zinc is a moderately reactive, blue gray metal \ that tarnishes in moist air and burns in air with a bright bluish-green flame,\ giving off fumes of zinc oxide. It reacts with acids, alkalis and other non-metals.\ If not completely pure, zinc reacts with dilute acids to release hydrogen.");
我们创建第一个标签,锌元素的定义。
gtk_label_set_line_wrap(GTK_LABEL(label2), TRUE);
如果文本超出组件大小,gtk_label_set_line_wrap
函数会换行。
hseparator = gtk_hseparator_new();
gtk_hseparator_new
创建一个新的 GtkHSeparator
。
gtk_box_pack_start(GTK_BOX(vbox), label1, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hseparator, FALSE, TRUE, 10); gtk_box_pack_start(GTK_BOX(vbox), label2, FALSE, TRUE, 0);
我们将分隔符放置在标签之间。

GtkEntry
GtkEntry
是一个单行文本输入字段。此组件用于输入文本数据。
#include <gtk/gtk.h> int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *table; GtkWidget *label1; GtkWidget *label2; GtkWidget *label3; GtkWidget *entry1; GtkWidget *entry2; GtkWidget *entry3; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(window), "GtkEntry"); gtk_container_set_border_width(GTK_CONTAINER(window), 10); table = gtk_table_new(3, 2, FALSE); gtk_container_add(GTK_CONTAINER(window), table); label1 = gtk_label_new("Name"); label2 = gtk_label_new("Age"); label3 = gtk_label_new("Occupation"); gtk_table_attach(GTK_TABLE(table), label1, 0, 1, 0, 1, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), label2, 0, 1, 1, 2, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), label3, 0, 1, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); entry1 = gtk_entry_new(); entry2 = gtk_entry_new(); entry3 = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry1, 1, 2, 0, 1, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), entry2, 1, 2, 1, 2, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), entry3, 1, 2, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_widget_show_all(window); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return 0; }
在我们的示例中,我们显示了三个文本输入框和三个标签。
table = gtk_table_new(3, 2, FALSE); gtk_container_add(GTK_CONTAINER(window), table);
为了组织我们的组件,我们使用表格容器组件。
entry1 = gtk_entry_new();
gtk_entry_new
函数创建一个新的 GtkEntry
。
gtk_table_attach(GTK_TABLE(table), entry1, 1, 2, 0, 1, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), entry2, 1, 2, 1, 2, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5); gtk_table_attach(GTK_TABLE(table), entry3, 1, 2, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
我们将组件附加到表格组件。

GtkImage
GtkImage
是一个用于显示图像的组件。
#include <gtk/gtk.h> int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *image; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(window), "Red Rock"); image = gtk_image_new_from_file("redrock.jpg"); gtk_container_add(GTK_CONTAINER(window), image); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
在我们的示例中,我们显示了城堡的图像。
image = gtk_image_new_from_file("redrock.png");
gtk_image_new_from_file
从指定的文件名创建一个新的 GtkImage
。如果找不到或无法加载该文件,则生成的 GtkImage
将显示一个“损坏的图像”图标。
gtk_container_add(GTK_CONTAINER(window), image);
图像已添加到窗口容器中。
GtkStatusbar
GtkStatusbar
显示状态信息。它位于应用程序窗口的底部。
#include <gtk/gtk.h> void button_pressed(GtkWidget *widget, gpointer window) { gchar *str; str = g_strdup_printf("%s button clicked", gtk_button_get_label(GTK_BUTTON(widget))); gtk_statusbar_push(GTK_STATUSBAR(window), gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str); g_free(str); } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *halign; GtkWidget *balign; GtkWidget *button1; GtkWidget *button2; GtkWidget *statusbar; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); gtk_window_set_title(GTK_WINDOW(window), "GtkStatusbar"); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); halign = gtk_alignment_new(0, 0, 0, 0); gtk_container_add(GTK_CONTAINER(halign), hbox); gtk_box_pack_start(GTK_BOX(vbox), halign, TRUE, TRUE, 5); button1 = gtk_button_new_with_label("OK"); gtk_widget_set_size_request(button1, 70, 30 ); button2 = gtk_button_new_with_label("Apply"); gtk_widget_set_size_request(button2, 70, 30 ); gtk_box_pack_start(GTK_BOX(hbox), button1, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), button2, FALSE, FALSE, 0); balign = gtk_alignment_new(0, 1, 1, 0); statusbar = gtk_statusbar_new(); gtk_container_add(GTK_CONTAINER(balign), statusbar); gtk_box_pack_start(GTK_BOX(vbox), balign, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_pressed), G_OBJECT(statusbar)); g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_pressed), G_OBJECT(statusbar)); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
在代码示例中,有两个按钮和一个状态栏。如果单击该按钮,则会在状态栏中显示一条消息。它说明按下了哪个按钮。
gchar *str; str = g_strdup_printf("Button %s clicked", gtk_button_get_label(GTK_BUTTON(widget)));
该消息使用 g_strdup_printf
函数构建。我们使用 gtk_button_get_label
函数获取按钮的标签。
gtk_statusbar_push(GTK_STATUSBAR(window), gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str);
我们在状态栏中显示消息。gtk_statusbar_push
函数将新消息推送到状态栏的堆栈中。该函数需要一个上下文 ID,该 ID 由 gtk_statusbar_get_context_id
函数返回。
statusbar = gtk_statusbar_new();
gtk_statusbar_new
函数创建一个新的 GtkStatusbar
组件。

GtkIconView
GtkIconView
是一个以网格形式显示图标列表的组件。它使用 GtkListStore
来存储其数据。
#include <gtk/gtk.h> #include <assert.h> enum { COL_DISPLAY_NAME, COL_PIXBUF, NUM_COLS }; GtkTreeModel *init_model(void) { GtkListStore *list_store; GdkPixbuf *p1, *p2, *p3, *p4; GtkTreeIter iter; GError *err = NULL; p1 = gdk_pixbuf_new_from_file("ubuntu.png", &err); p2 = gdk_pixbuf_new_from_file("gnumeric.png", &err); p3 = gdk_pixbuf_new_from_file("blender.png", &err); p4 = gdk_pixbuf_new_from_file("inkscape.png", &err); assert(err==NULL); list_store = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME, "Ubuntu", COL_PIXBUF, p1, -1); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME, "Gnumeric", COL_PIXBUF, p2, -1); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME, "Blender", COL_PIXBUF, p3, -1); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME, "Inkscape", COL_PIXBUF, p4, -1); g_object_unref(p1); g_object_unref(p2); g_object_unref(p3); g_object_unref(p4); return GTK_TREE_MODEL(list_store); } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *icon_view; GtkWidget *sw; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "IconView"); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_window_set_default_size(GTK_WINDOW(window), 350, 300); sw = gtk_scrolled_window_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(window), sw); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); icon_view = gtk_icon_view_new_with_model(init_model()); gtk_container_add(GTK_CONTAINER(sw), icon_view); gtk_icon_view_set_text_column(GTK_ICON_VIEW(icon_view), COL_DISPLAY_NAME); gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(icon_view), COL_PIXBUF); gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(icon_view), GTK_SELECTION_MULTIPLE); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
该示例显示了 4 个图标。这些图标代表了四个著名的开源项目。
p1 = gdk_pixbuf_new_from_file("ubuntu.png", &err); p2 = gdk_pixbuf_new_from_file("gnumeric.png", &err); p3 = gdk_pixbuf_new_from_file("blender.png", &err); p4 = gdk_pixbuf_new_from_file("inkscape.png", &err);
我们使用 gdk_pixbuf_new_from_file
函数从磁盘加载四个图像。
list_store = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF);
gtk_list_store_new
函数创建一个 GtkListStore
,它是 GtkTreeView
和 GtkIconView
组件的列表模型。我们存储文本和 pixbuf 数据。
gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME, "ubuntu", COL_PIXBUF, p1, -1);
此代码将新行添加到模型中。
icon_view = gtk_icon_view_new_with_model(init_model());
gtk_icon_view_new_with_model
使用 GtkTreeModel
创建一个新的 GtkIconView
组件。
gtk_container_add(GTK_CONTAINER(sw), icon_view);
GtkIconView
是一个容器组件。我们将其添加到 GtkScrolledWindow
中。
gtk_icon_view_set_text_column(GTK_ICON_VIEW(icon_view), COL_DISPLAY_NAME);
gtk_icon_view_set_text_column
函数设置哪个列是字符串列。
gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(icon_view), COL_PIXBUF);
gtk_icon_view_set_pixbuf_column
函数设置哪个是带有 pixbuf 的列。
gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(icon_view), GTK_SELECTION_MULTIPLE);
gtk_icon_view_set_selection_mode
设置 GtkIconView
的选择模式。选择 GTK_SELECTION_MULTIPLE
模式,可以选择多个图标。

在本 GTK+ 教程中,我们继续介绍了 GTK+ 组件。