原文: http://zetcode.com/gui/gtk2/gtkwidgetsII/

在 GTK+ 编程教程的这一部分中,我们将继续介绍各种 GTK+ 小部件。

GktComboBoxText

GktComboBoxText是一个小部件,允许用户从选项列表中进行选择。 选项是字符串。

combobox.c

  1. #include <gtk/gtk.h>
  2. void combo_selected(GtkWidget *widget, gpointer window) {
  3. gchar *text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
  4. gtk_label_set_text(GTK_LABEL(window), text);
  5. g_free(text);
  6. }
  7. int main(int argc, char *argv[]) {
  8. GtkWidget *window;
  9. GtkWidget *hbox;
  10. GtkWidget *vbox;
  11. GtkWidget *combo;
  12. GtkWidget *label;
  13. gtk_init(&argc, &argv);
  14. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  15. gtk_window_set_title(GTK_WINDOW(window), "GtkComboBox");
  16. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  17. gtk_container_set_border_width(GTK_CONTAINER(window), 15);
  18. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  19. hbox = gtk_hbox_new(FALSE, 0);
  20. vbox = gtk_vbox_new(FALSE, 15);
  21. combo = gtk_combo_box_new_text();
  22. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu");
  23. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Arch");
  24. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Fedora");
  25. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Mint");
  26. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Gentoo");
  27. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Debian");
  28. gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0);
  29. label = gtk_label_new("...");
  30. gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  31. gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
  32. gtk_container_add(GTK_CONTAINER(window), hbox);
  33. g_signal_connect(G_OBJECT(window), "destroy",
  34. G_CALLBACK(gtk_main_quit), NULL);
  35. g_signal_connect(G_OBJECT(combo), "changed",
  36. G_CALLBACK(combo_selected), (gpointer) label);
  37. gtk_widget_show_all(window);
  38. gtk_main();
  39. return 0;
  40. }

该示例显示了一个组合框和一个标签。 组合框具有六个选项的列表。 这些是 Linux 发行版的名称。 标签窗口小部件显示了从组合框中选择的选项。

  1. combo = gtk_combo_box_text_new();

gtk_combo_box_text_new()函数创建一个简单的纯文本组合框。

  1. gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu");

gtk_combo_box_text_append_text()函数将一个字符串附加到组合框中存储的字符串列表中。

  1. label = gtk_label_new("-");

创建一个新的标签小部件。

  1. gchar *text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
  2. gtk_label_set_text(GTK_LABEL(window), text);
  3. g_free(text);

我们得到选定的文本,并为其设置标签文本。 gtk_combo_box_get_active_text()函数在组合框中返回当前活动的字符串。 我们使用gtk_label_set_text()函数将字符串设置为标签。

GTK  小部件 II - 图1

图:GktComboBoxText

GtkHSeparator

GtkHSeparator是水平分隔符。 这是一种装饰小部件。 还有一个姐妹GtkVSeparator小部件。

separator.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *label1;
  5. GtkWidget *label2;
  6. GtkWidget *hseparator;
  7. GtkWidget *vbox;
  8. gtk_init(&argc, &argv);
  9. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  10. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  11. gtk_window_set_title(GTK_WINDOW(window), "GtkHSeparator");
  12. gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
  13. gtk_container_set_border_width(GTK_CONTAINER(window), 10);
  14. label1 = gtk_label_new("Zinc is a moderately reactive, blue gray metal \
  15. that tarnishes in moist air and burns in air with a bright bluish-green flame,\
  16. giving off fumes of zinc oxide. It reacts with acids, alkalis and other non-metals.\
  17. If not completely pure, zinc reacts with dilute acids to release hydrogen.");
  18. gtk_label_set_line_wrap(GTK_LABEL(label1), TRUE);
  19. label2 = gtk_label_new("Copper is an essential trace nutrient to all high \
  20. plants and animals. In animals, including humans, it is found primarily in \
  21. the bloodstream, as a co-factor in various enzymes, and in copper-based pigments. \
  22. However, in sufficient amounts, copper can be poisonous and even fatal to organisms.");
  23. gtk_label_set_line_wrap(GTK_LABEL(label2), TRUE);
  24. vbox = gtk_vbox_new(FALSE, 10);
  25. gtk_container_add(GTK_CONTAINER(window), vbox);
  26. hseparator = gtk_hseparator_new();
  27. gtk_box_pack_start(GTK_BOX(vbox), label1, FALSE, TRUE, 0);
  28. gtk_box_pack_start(GTK_BOX(vbox), hseparator, FALSE, TRUE, 10);
  29. gtk_box_pack_start(GTK_BOX(vbox), label2, FALSE, TRUE, 0);
  30. g_signal_connect_swapped(G_OBJECT(window), "destroy",
  31. G_CALLBACK(gtk_main_quit), G_OBJECT(window));
  32. gtk_widget_show_all(window);
  33. gtk_main();
  34. return 0;
  35. }

该代码示例显示了两种化学元素的定义; 它们由水平分隔符分隔。 这使示例在视觉上更具吸引力。

  1. label1 = gtk_label_new("Zinc is a moderately reactive, blue gray metal \
  2. that tarnishes in moist air and burns in air with a bright bluish-green flame,\
  3. giving off fumes of zinc oxide. It reacts with acids, alkalis and other non-metals.\
  4. If not completely pure, zinc reacts with dilute acids to release hydrogen.");

我们创建第一个标签,即锌元素的定义。

  1. gtk_label_set_line_wrap(GTK_LABEL(label2), TRUE);

如果文本超过小部件的大小,则gtk_label_set_line_wrap()函数将换行。

  1. hseparator = gtk_hseparator_new();

gtk_hseparator_new()创建一个新的GtkHSeparator

  1. gtk_box_pack_start(GTK_BOX(vbox), label1, FALSE, TRUE, 0);
  2. gtk_box_pack_start(GTK_BOX(vbox), hseparator, FALSE, TRUE, 10);
  3. gtk_box_pack_start(GTK_BOX(vbox), label2, FALSE, TRUE, 0);

我们将分隔符放在标签之间。

GTK  小部件 II - 图2

图:GtkHSeparator

GtkEntry

GtkEntry是单行文本输入字段。 该小部件用于输入文本数据。

entry.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *table;
  5. GtkWidget *label1;
  6. GtkWidget *label2;
  7. GtkWidget *label3;
  8. GtkWidget *entry1;
  9. GtkWidget *entry2;
  10. GtkWidget *entry3;
  11. gtk_init(&argc, &argv);
  12. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  13. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  14. gtk_window_set_title(GTK_WINDOW(window), "GtkEntry");
  15. gtk_container_set_border_width(GTK_CONTAINER(window), 10);
  16. table = gtk_table_new(3, 2, FALSE);
  17. gtk_container_add(GTK_CONTAINER(window), table);
  18. label1 = gtk_label_new("Name");
  19. label2 = gtk_label_new("Age");
  20. label3 = gtk_label_new("Occupation");
  21. gtk_table_attach(GTK_TABLE(table), label1, 0, 1, 0, 1,
  22. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  23. gtk_table_attach(GTK_TABLE(table), label2, 0, 1, 1, 2,
  24. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  25. gtk_table_attach(GTK_TABLE(table), label3, 0, 1, 2, 3,
  26. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  27. entry1 = gtk_entry_new();
  28. entry2 = gtk_entry_new();
  29. entry3 = gtk_entry_new();
  30. gtk_table_attach(GTK_TABLE(table), entry1, 1, 2, 0, 1,
  31. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  32. gtk_table_attach(GTK_TABLE(table), entry2, 1, 2, 1, 2,
  33. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  34. gtk_table_attach(GTK_TABLE(table), entry3, 1, 2, 2, 3,
  35. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  36. gtk_widget_show_all(window);
  37. g_signal_connect(window, "destroy",
  38. G_CALLBACK(gtk_main_quit), NULL);
  39. gtk_main();
  40. return 0;
  41. }

在我们的示例中,我们显示了三个文本条目和三个标签。

  1. table = gtk_table_new(3, 2, FALSE);
  2. gtk_container_add(GTK_CONTAINER(window), table);

为了组织小部件,我们使用表容器小部件。

  1. entry1 = gtk_entry_new();

gtk_entry_new()函数创建一个新的GtkEntry

  1. gtk_table_attach(GTK_TABLE(table), entry1, 1, 2, 0, 1,
  2. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  3. gtk_table_attach(GTK_TABLE(table), entry2, 1, 2, 1, 2,
  4. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);
  5. gtk_table_attach(GTK_TABLE(table), entry3, 1, 2, 2, 3,
  6. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 5, 5);

我们将这些小部件附加到表小部件。

GTK  小部件 II - 图3

图:GtkEntry

GtkImage

GtkImage是用于显示图像的小部件。

image.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *image;
  5. gtk_init(&argc, &argv);
  6. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  7. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  8. gtk_window_set_title(GTK_WINDOW(window), "Red Rock");
  9. image = gtk_image_new_from_file("redrock.jpg");
  10. gtk_container_add(GTK_CONTAINER(window), image);
  11. g_signal_connect(G_OBJECT(window), "destroy",
  12. G_CALLBACK(gtk_main_quit), NULL);
  13. gtk_widget_show_all(window);
  14. gtk_main();
  15. return 0;
  16. }

在我们的示例中,我们显示了城堡的图像。

  1. image = gtk_image_new_from_file("redrock.png");

gtk_image_new_from_file()从指定的文件名创建一个新的GtkImage。 如果找不到文件或无法加载文件,则显示的GtkImage将显示“图像损坏”图标。

  1. gtk_container_add(GTK_CONTAINER(window), image);

图像被添加到窗口容器中。

GtkStatusbar

GtkStatusbar显示状态信息。 它位于应用窗口的底部。

statusbar.c

  1. #include <gtk/gtk.h>
  2. void button_pressed(GtkWidget *widget, gpointer window) {
  3. gchar *str;
  4. str = g_strdup_printf("%s button clicked",
  5. gtk_button_get_label(GTK_BUTTON(widget)));
  6. gtk_statusbar_push(GTK_STATUSBAR(window),
  7. gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str);
  8. g_free(str);
  9. }
  10. int main(int argc, char *argv[]) {
  11. GtkWidget *window;
  12. GtkWidget *hbox;
  13. GtkWidget *vbox;
  14. GtkWidget *halign;
  15. GtkWidget *balign;
  16. GtkWidget *button1;
  17. GtkWidget *button2;
  18. GtkWidget *statusbar;
  19. gtk_init(&argc, &argv);
  20. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  21. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  22. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  23. gtk_window_set_title(GTK_WINDOW(window), "GtkStatusbar");
  24. vbox = gtk_vbox_new(FALSE, 0);
  25. hbox = gtk_hbox_new(FALSE, 0);
  26. gtk_container_add(GTK_CONTAINER(window), vbox);
  27. halign = gtk_alignment_new(0, 0, 0, 0);
  28. gtk_container_add(GTK_CONTAINER(halign), hbox);
  29. gtk_box_pack_start(GTK_BOX(vbox), halign, TRUE, TRUE, 5);
  30. button1 = gtk_button_new_with_label("OK");
  31. gtk_widget_set_size_request(button1, 70, 30 );
  32. button2 = gtk_button_new_with_label("Apply");
  33. gtk_widget_set_size_request(button2, 70, 30 );
  34. gtk_box_pack_start(GTK_BOX(hbox), button1, FALSE, FALSE, 5);
  35. gtk_box_pack_start(GTK_BOX(hbox), button2, FALSE, FALSE, 0);
  36. balign = gtk_alignment_new(0, 1, 1, 0);
  37. statusbar = gtk_statusbar_new();
  38. gtk_container_add(GTK_CONTAINER(balign), statusbar);
  39. gtk_box_pack_start(GTK_BOX(vbox), balign, FALSE, FALSE, 0);
  40. g_signal_connect(G_OBJECT(button1), "clicked",
  41. G_CALLBACK(button_pressed), G_OBJECT(statusbar));
  42. g_signal_connect(G_OBJECT(button2), "clicked",
  43. G_CALLBACK(button_pressed), G_OBJECT(statusbar));
  44. g_signal_connect(G_OBJECT(window), "destroy",
  45. G_CALLBACK(gtk_main_quit), NULL);
  46. gtk_widget_show_all(window);
  47. gtk_main();
  48. return 0;
  49. }

在代码示例中,有两个按钮和一个状态栏。 如果单击按钮,状态栏中将显示一条消息。 它说按下了哪个按钮。

  1. gchar *str;
  2. str = g_strdup_printf("Button %s clicked",
  3. gtk_button_get_label(GTK_BUTTON(widget)));

该消息是使用g_strdup_printf()函数构建的。 我们使用gtk_button_get_label()函数获得按钮的标签。

  1. gtk_statusbar_push(GTK_STATUSBAR(window),
  2. gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str);

我们在状态栏中显示该消息。 gtk_statusbar_push()函数将新消息推送到状态栏的栈上。 该函数需要一个上下文 ID,该上下文 ID 由gtk_statusbar_get_context_id()函数返回。

  1. statusbar = gtk_statusbar_new();

gtk_statusbar_new()函数创建一个新的GtkStatusbar小部件。

GTK  小部件 II - 图4

图:GtkStatusbar

GtkIconView

GtkIconView是一个小部件,在网格中显示图标列表。 它使用GtkListStore存储其数据。

iconview.c

  1. #include <gtk/gtk.h>
  2. #include <assert.h>
  3. enum {
  4. COL_DISPLAY_NAME,
  5. COL_PIXBUF,
  6. NUM_COLS
  7. };
  8. GtkTreeModel *init_model(void) {
  9. GtkListStore *list_store;
  10. GdkPixbuf *p1, *p2, *p3, *p4;
  11. GtkTreeIter iter;
  12. GError *err = NULL;
  13. p1 = gdk_pixbuf_new_from_file("ubuntu.png", &err);
  14. p2 = gdk_pixbuf_new_from_file("gnumeric.png", &err);
  15. p3 = gdk_pixbuf_new_from_file("blender.png", &err);
  16. p4 = gdk_pixbuf_new_from_file("inkscape.png", &err);
  17. assert(err==NULL);
  18. list_store = gtk_list_store_new(NUM_COLS,
  19. G_TYPE_STRING, GDK_TYPE_PIXBUF);
  20. gtk_list_store_append(list_store, &iter);
  21. gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME,
  22. "Ubuntu", COL_PIXBUF, p1, -1);
  23. gtk_list_store_append(list_store, &iter);
  24. gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME,
  25. "Gnumeric", COL_PIXBUF, p2, -1);
  26. gtk_list_store_append(list_store, &iter);
  27. gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME,
  28. "Blender", COL_PIXBUF, p3, -1);
  29. gtk_list_store_append(list_store, &iter);
  30. gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME,
  31. "Inkscape", COL_PIXBUF, p4, -1);
  32. g_object_unref(p1);
  33. g_object_unref(p2);
  34. g_object_unref(p3);
  35. g_object_unref(p4);
  36. return GTK_TREE_MODEL(list_store);
  37. }
  38. int main(int argc, char *argv[]) {
  39. GtkWidget *window;
  40. GtkWidget *icon_view;
  41. GtkWidget *sw;
  42. gtk_init(&argc, &argv);
  43. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  44. gtk_window_set_title(GTK_WINDOW(window), "IconView");
  45. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  46. gtk_container_set_border_width(GTK_CONTAINER(window), 10);
  47. gtk_window_set_default_size(GTK_WINDOW(window), 350, 300);
  48. sw = gtk_scrolled_window_new(NULL, NULL);
  49. gtk_container_add(GTK_CONTAINER(window), sw);
  50. gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
  51. GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  52. gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
  53. GTK_SHADOW_IN);
  54. icon_view = gtk_icon_view_new_with_model(init_model());
  55. gtk_container_add(GTK_CONTAINER(sw), icon_view);
  56. gtk_icon_view_set_text_column(GTK_ICON_VIEW(icon_view),
  57. COL_DISPLAY_NAME);
  58. gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(icon_view), COL_PIXBUF);
  59. gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(icon_view),
  60. GTK_SELECTION_MULTIPLE);
  61. g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
  62. gtk_widget_show_all(window);
  63. gtk_main();
  64. return 0;
  65. }

该示例显示 4 个图标。 这些图标代表四个著名的开源项目。

  1. p1 = gdk_pixbuf_new_from_file("ubuntu.png", &err);
  2. p2 = gdk_pixbuf_new_from_file("gnumeric.png", &err);
  3. p3 = gdk_pixbuf_new_from_file("blender.png", &err);
  4. p4 = gdk_pixbuf_new_from_file("inkscape.png", &err);

我们使用gdk_pixbuf_new_from_file()函数从磁盘加载四个图像。

  1. list_store = gtk_list_store_new(NUM_COLS,
  2. G_TYPE_STRING, GDK_TYPE_PIXBUF);

gtk_list_store_new()函数创建一个GtkListStore,它是GtkTreeViewGtkIconView小部件的列表模型。 我们存储文本和pixbuf数据。

  1. gtk_list_store_append(list_store, &iter);
  2. gtk_list_store_set(list_store, &iter, COL_DISPLAY_NAME,
  3. "ubuntu", COL_PIXBUF, p1, -1);

此代码将新行添加到模型中。

  1. icon_view = gtk_icon_view_new_with_model(init_model());

gtk_icon_view_new_with_model()使用GtkTreeModel创建一个新的GtkIconView小部件。

  1. gtk_container_add(GTK_CONTAINER(sw), icon_view);

GtkIconView是一个容器小部件。 我们将其添加到GtkScrolledWindow中。

  1. gtk_icon_view_set_text_column(GTK_ICON_VIEW(icon_view),
  2. COL_DISPLAY_NAME);

gtk_icon_view_set_text_column()函数设置哪一列是字符串列。

  1. gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(icon_view),
  2. COL_PIXBUF);

gtk_icon_view_set_pixbuf_column()函数设置具有pixbufs的列。

  1. gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(icon_view),
  2. GTK_SELECTION_MULTIPLE);

gtk_icon_view_set_selection_mode()设置GtkIconView的选择模式。 选择GTK_SELECTION_MULTIPLE模式,可以选择多个图标。

GTK  小部件 II - 图5

图:图标 View

在 GTK+ 教程的这一部分中,我们将继续介绍 GTK+ 小部件。