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

在 GTK+ 编程教程的这一部分中,我们使用菜单和工具栏。菜单栏是 GUI 应用的常见部分。 它是位于各个菜单中的一组命令。

GtkMenuBar是创建菜单栏的窗口小部件。 它包含一对多GtkMenuItems。 菜单项是用户可以选择的对象。 GtkMenu实现了一个由GtkMenuItem对象列表组成的下拉菜单,用户可以对其进行导航和激活以执行应用功能。 GtkMenu附加到菜单栏的菜单项或另一个菜单的菜单项。

GTK  中的菜单和工具栏 - 图1

图:菜单

该图显示了菜单栏及其菜单的结构。

简单菜单示例

在第一个示例中,我们创建带有一个“文件”菜单的菜单栏。

simplemenu.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *vbox;
  5. GtkWidget *menubar;
  6. GtkWidget *fileMenu;
  7. GtkWidget *fileMi;
  8. GtkWidget *quitMi;
  9. gtk_init(&argc, &argv);
  10. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  11. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  12. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  13. gtk_window_set_title(GTK_WINDOW(window), "Simple menu");
  14. vbox = gtk_vbox_new(FALSE, 0);
  15. gtk_container_add(GTK_CONTAINER(window), vbox);
  16. menubar = gtk_menu_bar_new();
  17. fileMenu = gtk_menu_new();
  18. fileMi = gtk_menu_item_new_with_label("File");
  19. quitMi = gtk_menu_item_new_with_label("Quit");
  20. gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
  21. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
  22. gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
  23. gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  24. g_signal_connect(G_OBJECT(window), "destroy",
  25. G_CALLBACK(gtk_main_quit), NULL);
  26. g_signal_connect(G_OBJECT(quitMi), "activate",
  27. G_CALLBACK(gtk_main_quit), NULL);
  28. gtk_widget_show_all(window);
  29. gtk_main();
  30. return 0;
  31. }

示例中的菜单具有一个菜单项。 通过选择项目,应用退出。

  1. menubar = gtk_menu_bar_new();

gtk_menu_bar_new()创建一个新的GtkMenuBar

  1. filemenu = gtk_menu_new();

gtk_menu_new()函数创建一个新的GtkMenu

  1. gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);

通过gtk_menu_item_set_submenu()函数将fileMenu设置为文件菜单项。 菜单是容纳菜单项的容器。 它们本身已插入特定的菜单项。

  1. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);

通过gtk_menu_shell_append()函数将quitMi添加到文件菜单。

  1. gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);

使用gtk_menu_shell_append()函数将文件菜单项添加到菜单栏。 GtkMenuGtkMenuBar均来自GtkMenuShell

  1. g_signal_connect(G_OBJECT(quitMi), "activate",
  2. G_CALLBACK(gtk_main_quit), NULL);

通过选择退出菜单项,我们终止了该应用。

GTK  中的菜单和工具栏 - 图2

图:简单菜单

子菜单

下一个示例演示如何创建子菜单。 子菜单是另一个菜单中的菜单。

submenu.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *vbox;
  5. GtkWidget *menubar;
  6. GtkWidget *fileMenu;
  7. GtkWidget *imprMenu;
  8. GtkWidget *sep;
  9. GtkWidget *fileMi;
  10. GtkWidget *imprMi;
  11. GtkWidget *feedMi;
  12. GtkWidget *bookMi;
  13. GtkWidget *mailMi;
  14. GtkWidget *quitMi;
  15. gtk_init(&argc, &argv);
  16. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  17. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  18. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  19. gtk_window_set_title(GTK_WINDOW(window), "Submenu");
  20. vbox = gtk_vbox_new(FALSE, 0);
  21. gtk_container_add(GTK_CONTAINER(window), vbox);
  22. menubar = gtk_menu_bar_new();
  23. fileMenu = gtk_menu_new();
  24. fileMi = gtk_menu_item_new_with_label("File");
  25. imprMenu = gtk_menu_new();
  26. imprMi = gtk_menu_item_new_with_label("Import");
  27. feedMi = gtk_menu_item_new_with_label("Import news feed...");
  28. bookMi = gtk_menu_item_new_with_label("Import bookmarks...");
  29. mailMi = gtk_menu_item_new_with_label("Import mail...");
  30. gtk_menu_item_set_submenu(GTK_MENU_ITEM(imprMi), imprMenu);
  31. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), feedMi);
  32. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), bookMi);
  33. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), mailMi);
  34. sep = gtk_separator_menu_item_new();
  35. quitMi = gtk_menu_item_new_with_label("Quit");
  36. gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
  37. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), imprMi);
  38. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);
  39. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
  40. gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
  41. gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  42. g_signal_connect(G_OBJECT(window), "destroy",
  43. G_CALLBACK(gtk_main_quit), NULL);
  44. g_signal_connect(G_OBJECT(quitMi), "activate",
  45. G_CALLBACK(gtk_main_quit), NULL);
  46. gtk_widget_show_all(window);
  47. gtk_main();
  48. return 0;
  49. }

该示例在另一个菜单内创建一个菜单。 子菜单具有三个菜单项。 我们还添加了一个水平分隔符。

  1. imprMenu = gtk_menu_new();
  2. imprMi = gtk_menu_item_new_with_label("Import");
  3. feedMi = gtk_menu_item_new_with_label("Import news feed...");
  4. bookMi = gtk_menu_item_new_with_label("Import bookmarks...");
  5. mailMi = gtk_menu_item_new_with_label("Import mail...");

这是带有菜单项的子菜单。

  1. gtk_menu_item_set_submenu(GTK_MENU_ITEM(imprMi), imprMenu);

imprMenu子菜单被添加到其自己的菜单项中。

  1. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), feedMi);
  2. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), bookMi);
  3. gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), mailMi);

使用gtk_menu_shell_append()函数将三个菜单项添加到子菜单。

  1. sep = gtk_separator_menu_item_new();

使用gtk_separator_menu_item_new()函数创建水平菜单分隔符。

  1. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), imprMi);
  2. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);

imprMi和分隔符通过gtk_menu_shell_append()函数添加到文件菜单。

GTK  中的菜单和工具栏 - 图3

图:子菜单

图像菜单,助记符和加速器

GtkImageMenuItem是一个菜单项,在文本标签旁边带有一个图标。 由于用户可以禁用菜单图标的显示,因此我们仍然需要填写文本标签。加速器是用于激活菜单项的键盘快捷键。助记符是 GUI 元素的键盘快捷键。 它们以带下划线的字符表示。 请注意,在某些环境中,我们首先需要按无鼠标修饰符(通常为Alt)以显示带下划线的字符。

我们可能还配置了不显示菜单图像的环境。 要打开菜单图像,我们启动gconf-editor并转到/desktop/gnome/interface/menus_have_icons并检查选项。

imagemenu.c

  1. #include <gtk/gtk.h>
  2. #include <gdk/gdkkeysyms.h>
  3. int main(int argc, char *argv[]) {
  4. GtkWidget *window;
  5. GtkWidget *vbox;
  6. GtkWidget *menubar;
  7. GtkWidget *fileMenu;
  8. GtkWidget *fileMi;
  9. GtkWidget *newMi;
  10. GtkWidget *openMi;
  11. GtkWidget *quitMi;
  12. GtkWidget *sep;
  13. GtkAccelGroup *accel_group = NULL;
  14. gtk_init(&argc, &argv);
  15. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  16. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  17. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  18. gtk_window_set_title(GTK_WINDOW(window), "Images");
  19. vbox = gtk_vbox_new(FALSE, 0);
  20. gtk_container_add(GTK_CONTAINER(window), vbox);
  21. menubar = gtk_menu_bar_new();
  22. fileMenu = gtk_menu_new();
  23. accel_group = gtk_accel_group_new();
  24. gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
  25. fileMi = gtk_menu_item_new_with_mnemonic("_File");
  26. newMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
  27. openMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
  28. sep = gtk_separator_menu_item_new();
  29. quitMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);
  30. gtk_widget_add_accelerator(quitMi, "activate", accel_group,
  31. GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
  32. gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
  33. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), newMi);
  34. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), openMi);
  35. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);
  36. gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
  37. gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
  38. gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  39. g_signal_connect(G_OBJECT(window), "destroy",
  40. G_CALLBACK(gtk_main_quit), NULL);
  41. g_signal_connect(G_OBJECT(quitMi), "activate",
  42. G_CALLBACK(gtk_main_quit), NULL);
  43. gtk_widget_show_all(window);
  44. gtk_main();
  45. return 0;
  46. }

该示例包含三个带有图标的菜单项。 菜单项可以用助记符选择。 退出菜单项具有键盘加速器。

  1. accel_group = gtk_accel_group_new();
  2. gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
  3. ...
  4. quitMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);
  5. gtk_widget_add_accelerator(quitMi, "activate", accel_group,
  6. GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);

加速器组是一组键盘加速器,通常附加到顶层窗口。 在这里,我们创建 Ctrl + Q 键盘加速器。

  1. fileMi = gtk_menu_item_new_with_mnemonic("_File");

gtk_menu_item_new_with_mnemonic()创建一个可以带有助记符的菜单项。 标签中的下划线表示菜单项的助记符。 该字符与无鼠标修饰符(通常为Alt)结合在一起。 在我们的情况下,我们创建了 Alt + F 助记符。

  1. newMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
  2. openMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);

gtk_image_menu_item_new_from_stock()创建一个GtkImageMenuItem,其中包含来自库存项目的图像和文本。

GTK  中的菜单和工具栏 - 图4

图:带图标的菜单项

CheckMenuItem

GtkCheckMenuItem是带有复选框的菜单项。

checkmenuitem.c

  1. #include <gtk/gtk.h>
  2. void toggle_statusbar(GtkWidget *widget, gpointer statusbar) {
  3. if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
  4. gtk_widget_show(statusbar);
  5. } else {
  6. gtk_widget_hide(statusbar);
  7. }
  8. }
  9. int main(int argc, char *argv[]) {
  10. GtkWidget *window;
  11. GtkWidget *vbox;
  12. GtkWidget *menubar;
  13. GtkWidget *viewmenu;
  14. GtkWidget *view;
  15. GtkWidget *tog_stat;
  16. GtkWidget *statusbar;
  17. gtk_init(&argc, &argv);
  18. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  19. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  20. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  21. gtk_window_set_title(GTK_WINDOW(window), "GtkCheckMenuItem");
  22. vbox = gtk_vbox_new(FALSE, 0);
  23. gtk_container_add(GTK_CONTAINER(window), vbox);
  24. menubar = gtk_menu_bar_new();
  25. viewmenu = gtk_menu_new();
  26. view = gtk_menu_item_new_with_label("View");
  27. tog_stat = gtk_check_menu_item_new_with_label("View statusbar");
  28. gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tog_stat), TRUE);
  29. gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), viewmenu);
  30. gtk_menu_shell_append(GTK_MENU_SHELL(viewmenu), tog_stat);
  31. gtk_menu_shell_append(GTK_MENU_SHELL(menubar), view);
  32. gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  33. statusbar = gtk_statusbar_new();
  34. gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 0);
  35. g_signal_connect(G_OBJECT(window), "destroy",
  36. G_CALLBACK(gtk_main_quit), NULL);
  37. g_signal_connect(G_OBJECT(tog_stat), "activate",
  38. G_CALLBACK(toggle_statusbar), statusbar);
  39. gtk_widget_show_all(window);
  40. gtk_main();
  41. return 0;
  42. }

该示例在“查看”菜单中包含一个GtkCheckMenuItem。 如果该复选框已激活,则显示状态栏小部件。

  1. tog_stat = gtk_check_menu_item_new_with_label("View statusbar");

gtk_check_menu_item_new_with_label()函数创建一个新的CheckMenuItem

  1. statusbar = gtk_statusbar_new();

gtk_statusbar_new()函数创建一个新的GtkStatusbar小部件。 它用于向用户报告次要消息。

  1. if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
  2. gtk_widget_show(statusbar);
  3. } else {
  4. gtk_widget_hide(statusbar);
  5. }

如果菜单项中的复选框被激活,我们将显示状态栏小部件。 否则状态栏将被隐藏。

GTK  中的菜单和工具栏 - 图5

图:GtkCheckMenuItem

弹出菜单

在下一个示例中,我们创建一个弹出菜单。 弹出菜单也称为上下文菜单。 当我们右键单击 GUI 对象时,通常会显示这种类型的菜单。

popupmenu.c

  1. #include <gtk/gtk.h>
  2. int show_popup(GtkWidget *widget, GdkEvent *event) {
  3. const gint RIGHT_CLICK = 3;
  4. if (event->type == GDK_BUTTON_PRESS) {
  5. GdkEventButton *bevent = (GdkEventButton *) event;
  6. if (bevent->button == RIGHT_CLICK) {
  7. gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL,
  8. bevent->button, bevent->time);
  9. }
  10. return TRUE;
  11. }
  12. return FALSE;
  13. }
  14. int main(int argc, char *argv[]) {
  15. GtkWidget *window;
  16. GtkWidget *ebox;
  17. GtkWidget *pmenu;
  18. GtkWidget *hideMi;
  19. GtkWidget *quitMi;
  20. gtk_init(&argc, &argv);
  21. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  22. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  23. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  24. gtk_window_set_title(GTK_WINDOW(window), "Popup menu");
  25. ebox = gtk_event_box_new();
  26. gtk_container_add(GTK_CONTAINER(window), ebox);
  27. pmenu = gtk_menu_new();
  28. hideMi = gtk_menu_item_new_with_label("Minimize");
  29. gtk_widget_show(hideMi);
  30. gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), hideMi);
  31. quitMi = gtk_menu_item_new_with_label("Quit");
  32. gtk_widget_show(quitMi);
  33. gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), quitMi);
  34. g_signal_connect_swapped(G_OBJECT(hideMi), "activate",
  35. G_CALLBACK(gtk_window_iconify), GTK_WINDOW(window));
  36. g_signal_connect(G_OBJECT(quitMi), "activate",
  37. G_CALLBACK(gtk_main_quit), NULL);
  38. g_signal_connect(G_OBJECT(window), "destroy",
  39. G_CALLBACK(gtk_main_quit), NULL);
  40. g_signal_connect_swapped(G_OBJECT(ebox), "button-press-event",
  41. G_CALLBACK(show_popup), pmenu);
  42. gtk_widget_show_all(window);
  43. gtk_main();
  44. return 0;
  45. }

在代码示例中,我们创建带有两个菜单项的弹出菜单。 第一个最小化窗口,第二个终止应用。

  1. ebox = gtk_event_box_new();
  2. gtk_container_add(GTK_CONTAINER(window), ebox);

为了处理按钮按下事件,我们创建了一个GtkEventBox

  1. pmenu = gtk_menu_new();

弹出菜单是GtkMenu

  1. hideMi = gtk_menu_item_new_with_label("Minimize");
  2. gtk_widget_show(hideMi);
  3. gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), hideMi);

第一个菜单项已添加到弹出菜单。

  1. g_signal_connect_swapped(G_OBJECT(hideMi), "activate",
  2. G_CALLBACK(gtk_window_iconify), GTK_WINDOW(window));

选择第一个菜单项将使窗口最小化。 我们将“隐藏”菜单项的activate信号连接到gtk_window_iconify()函数。 术语“图标化”是“最小化”的同义词。

  1. g_signal_connect_swapped(G_OBJECT(ebox), "button_press_event",
  2. G_CALLBACK(show_popup), pmenu);

当按下鼠标按钮时,会发出button-press-event信号。 我们将信号连接到show_popup()函数,然后将其传递给弹出菜单。

  1. if (event->type == GDK_BUTTON_PRESS) {

在事件处理器内部,我们检查按钮按下事件的类型。

  1. if (bevent->button == RIGHT_CLICK) {
  2. gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL,
  3. bevent->button, bevent->time);
  4. }

当触发信号的按钮是鼠标右键时,我们将显示带有gtk_menu_popup()函数的弹出菜单。

GTK  中的菜单和工具栏 - 图6

图:弹出菜单

工具栏

菜单将我们可以在应用中使用的命令分组。 使用工具栏可以快速访问最常用的命令。 GtkToolbar是 GTK+ 中的工具栏小部件。 工具栏可以包含GtkToolItem子类的实例,例如 GtkToolButtonGtkSeparatorToolItem

toolbar.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *vbox;
  5. GtkWidget *toolbar;
  6. GtkToolItem *newTb;
  7. GtkToolItem *openTb;
  8. GtkToolItem *saveTb;
  9. GtkToolItem *sep;
  10. GtkToolItem *exitTb;
  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_default_size(GTK_WINDOW(window), 300, 200);
  15. gtk_window_set_title(GTK_WINDOW(window), "toolbar");
  16. vbox = gtk_vbox_new(FALSE, 0);
  17. gtk_container_add(GTK_CONTAINER(window), vbox);
  18. toolbar = gtk_toolbar_new();
  19. gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
  20. newTb = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
  21. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), newTb, -1);
  22. openTb = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
  23. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), openTb, -1);
  24. saveTb = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
  25. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), saveTb, -1);
  26. sep = gtk_separator_tool_item_new();
  27. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
  28. exitTb = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
  29. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exitTb, -1);
  30. gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
  31. g_signal_connect(G_OBJECT(exitTb), "clicked",
  32. G_CALLBACK(gtk_main_quit), NULL);
  33. g_signal_connect(G_OBJECT(window), "destroy",
  34. G_CALLBACK(gtk_main_quit), NULL);
  35. gtk_widget_show_all(window);
  36. gtk_main();
  37. return 0;
  38. }

该代码示例创建了简单的工具栏示例。

  1. toolbar = gtk_toolbar_new();

gtk_toolbar_new()函数创建一个新的GtkToolBar小部件。

  1. gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS)

gtk_toolbar_set_style()函数将工具栏的视图更改为仅显示图标,仅显示文本或同时显示两者。 传递GTK_TOOLBAR_ICONS常量可使工具栏仅显示图标。

  1. newTb = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);

gtk_tool_button_new_from_stock()函数创建一个新的GtkToolButton,其中包含来自库存项目的图像和文本。

  1. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new, -1);

gtk_toolbar_insert()函数将GtkToolItem插入工具栏的指定位置。 如果位置为负,则该项目将附加到工具栏的末尾。

  1. sep = gtk_separator_tool_item_new();
  2. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);

gtk_separator_tool_item_new()函数创建一个新的GtkSeparatorToolItem。 它通过gtk_toolbar_insert()函数插入到工具栏中。

GTK  中的菜单和工具栏 - 图7

图:工具栏

撤销重做

下面的示例演示如何禁用工具栏上的工具栏按钮。 这是 GUI 编程中的常见做法。 例如,保存按钮; 如果我们将文档的所有更改都保存到磁盘上,则在大多数文本编辑器中,“保存”按钮均处于禁用状态。 这样,应用会向用户指示所有更改都已保存。

undoredo.c

  1. #include <gtk/gtk.h>
  2. void undo_redo(GtkWidget *widget, gpointer item) {
  3. static gint count = 2;
  4. const gchar *name = gtk_widget_get_name(widget);
  5. if (g_strcmp0(name, "undo") ) {
  6. count++;
  7. } else {
  8. count--;
  9. }
  10. if (count < 0) {
  11. gtk_widget_set_sensitive(widget, FALSE);
  12. gtk_widget_set_sensitive(item, TRUE);
  13. }
  14. if (count > 5) {
  15. gtk_widget_set_sensitive(widget, FALSE);
  16. gtk_widget_set_sensitive(item, TRUE);
  17. }
  18. }
  19. int main(int argc, char *argv[]) {
  20. GtkWidget *window;
  21. GtkWidget *vbox;
  22. GtkWidget *toolbar;
  23. GtkToolItem *undo;
  24. GtkToolItem *redo;
  25. GtkToolItem *sep;
  26. GtkToolItem *exit;
  27. gtk_init(&argc, &argv);
  28. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  29. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  30. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  31. gtk_window_set_title(GTK_WINDOW(window), "Undo redo");
  32. vbox = gtk_vbox_new(FALSE, 0);
  33. gtk_container_add(GTK_CONTAINER(window), vbox);
  34. toolbar = gtk_toolbar_new();
  35. gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
  36. gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
  37. undo = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
  38. gtk_widget_set_name(GTK_WIDGET(undo), "undo");
  39. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1);
  40. redo = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
  41. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), redo, -1);
  42. sep = gtk_separator_tool_item_new();
  43. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
  44. exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
  45. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
  46. gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
  47. g_signal_connect(G_OBJECT(undo), "clicked",
  48. G_CALLBACK(undo_redo), redo);
  49. g_signal_connect(G_OBJECT(redo), "clicked",
  50. G_CALLBACK(undo_redo), undo);
  51. g_signal_connect(G_OBJECT(exit), "clicked",
  52. G_CALLBACK(gtk_main_quit), NULL);
  53. g_signal_connect(G_OBJECT(window), "destroy",
  54. G_CALLBACK(gtk_main_quit), NULL);
  55. gtk_widget_show_all(window);
  56. gtk_main();
  57. return 0;
  58. }

我们的示例从 GTK+ 库存资源创建撤消和重做按钮。 单击几下后,每个按钮均被禁用。 按钮显示为灰色。

  1. if (count < 0) {
  2. gtk_widget_set_sensitive(widget, FALSE);
  3. gtk_widget_set_sensitive(item, TRUE);
  4. }
  5. if (count > 5) {
  6. gtk_widget_set_sensitive(widget, FALSE);
  7. gtk_widget_set_sensitive(item, TRUE);
  8. }

gtk_widget_set_sensitive()函数用于激活或禁用工具栏按钮。

GTK  中的菜单和工具栏 - 图8

图:撤销和重做

在本章中,我们介绍了 GTK+ 中的菜单和工具栏。