|
|
Строка 1: |
Строка 1: |
- | In this part of the GTK+ programming tutorial, we will work with menus and toolbars.
| |
| | | |
- | A <b>menubar</b> is one of the most common parts of the GUI application. It is a group of commands located in various menus. While in console applications you had to remember all those arcane commands, here we have most of the commands grouped into logical parts. There are accepted standards that further reduce the amount of time spending to learn a new application.
| |
- |
| |
- | == Simple menu example ==
| |
- |
| |
- | In our first example, we will create a menubar with one file menu. The menu will have only one menu item. By selecting the item the application quits.
| |
- |
| |
- | <source lang="cpp">
| |
- | #include <gtk/gtk.h>
| |
- |
| |
- |
| |
- | int main( int argc, char *argv[])
| |
- | {
| |
- |
| |
- | GtkWidget *window;
| |
- | GtkWidget *vbox;
| |
- |
| |
- | GtkWidget *menubar;
| |
- | GtkWidget *filemenu;
| |
- | GtkWidget *file;
| |
- | GtkWidget *quit;
| |
- |
| |
- | 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), 250, 200);
| |
- | gtk_window_set_title(GTK_WINDOW(window), "menu");
| |
- |
| |
- | vbox = gtk_vbox_new(FALSE, 0);
| |
- | gtk_container_add(GTK_CONTAINER(window), vbox);
| |
- |
| |
- | menubar = gtk_menu_bar_new();
| |
- | filemenu = gtk_menu_new();
| |
- |
| |
- | file = gtk_menu_item_new_with_label("File");
| |
- | quit = gtk_menu_item_new_with_label("Quit");
| |
- |
| |
- | gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
| |
- | gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);
| |
- |
| |
- | g_signal_connect_swapped(G_OBJECT(window), "destroy",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | g_signal_connect(G_OBJECT(quit), "activate",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | gtk_widget_show_all(window);
| |
- |
| |
- | gtk_main();
| |
- |
| |
- | return 0;
| |
- | }
| |
- |
| |
- | </source>
| |
- |
| |
- | Creating a menubar is a bit confusing. We must bear in mind that both a <b>menubar</b> and <b>menus</b> are derived from the same widget, namely a <b>menu shell</b>. <b>menu items</b> are only valid childs for menus. They are also used to implement submenus.
| |
- |
| |
- | <source lang="cpp">
| |
- | menubar = gtk_menu_bar_new();
| |
- | filemenu = gtk_menu_new();
| |
- | </source>
| |
- |
| |
- | In this code we create a menubar and a menu.
| |
- |
| |
- | <source lang="cpp">
| |
- | gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
| |
- | </source>
| |
- |
| |
- | This code line implements a file menu. The logic is that the menubar is a menu shell. file menu is also a menu shell.
| |
- | That's why we look at the file menu as a submenu or a subshell.
| |
- |
| |
- | <source lang="cpp">
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
| |
- | </source>
| |
- |
| |
- | Menu items are implemented by calling the <b>gtk_menu_shell_append()</b> function. menu items are appended to menu shells. In our case, quit menu item is appended to a file menu and also the file menu item is appended to the menubar.
| |
- |
| |
- | <source lang="cpp">
| |
- | g_signal_connect(G_OBJECT(quit), "activate",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- | </source>
| |
- |
| |
- | By selecting the quit menu item, we quit the application.
| |
- |
| |
- | [[image: gtk_faq_simplemenu.png | center]]
| |
- |
| |
- | == Image menus, mnemonics & accelerators ==
| |
- |
| |
- | In the next example, we will further explore the functionality that we can use in GTK+.
| |
- | <b>Accelerators</b> are keyboard shortcuts for activating a menu item. <b>Mnemonics</b> are keyboard shortcuts for GUI elements. They are represented as underlined characters.
| |
- |
| |
- | <source lang="cpp">
| |
- | #include <gtk/gtk.h>
| |
- | #include <gdk/gdkkeysyms.h>
| |
- |
| |
- | int main( int argc, char *argv[])
| |
- | {
| |
- |
| |
- | GtkWidget *window;
| |
- | GtkWidget *vbox;
| |
- |
| |
- | GtkWidget *menubar;
| |
- | GtkWidget *filemenu;
| |
- | GtkWidget *file;
| |
- | GtkWidget *new;
| |
- | GtkWidget *open;
| |
- | GtkWidget *quit;
| |
- |
| |
- | GtkWidget *sep;
| |
- |
| |
- | GtkAccelGroup *accel_group = NULL;
| |
- |
| |
- | 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), 250, 200);
| |
- | gtk_window_set_title(GTK_WINDOW(window), "menu");
| |
- |
| |
- | vbox = gtk_vbox_new(FALSE, 0);
| |
- | gtk_container_add(GTK_CONTAINER(window), vbox);
| |
- |
| |
- | menubar = gtk_menu_bar_new();
| |
- | filemenu = gtk_menu_new();
| |
- |
| |
- | accel_group = gtk_accel_group_new();
| |
- | gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
| |
- |
| |
- | file = gtk_menu_item_new_with_mnemonic("_File");
| |
- | new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
| |
- | open = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
| |
- | sep = gtk_separator_menu_item_new();
| |
- | quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);
| |
- |
| |
- | gtk_widget_add_accelerator(quit, "activate", accel_group,
| |
- | GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
| |
- |
| |
- |
| |
- | gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), new);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), sep);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
| |
- | gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);
| |
- |
| |
- | g_signal_connect_swapped(G_OBJECT(window), "destroy",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | g_signal_connect(G_OBJECT(quit), "activate",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | gtk_widget_show_all(window);
| |
- |
| |
- | gtk_main();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- |
| |
- | The example shows, how to add an image to our menu item. How to set up an accelerator and how to use mnemonics in our GTK+ applications.
| |
- |
| |
- | <source lang="cpp">
| |
- | accel_group = gtk_accel_group_new();
| |
- | gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
| |
- | ...
| |
- | quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);
| |
- | gtk_widget_add_accelerator(quit, "activate", accel_group,
| |
- | GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
| |
- | </source>
| |
- |
| |
- | An accelerator group is a group of keyboard accelerators, typically attached to a toplevel window.
| |
- | Here we create Ctrl + q keyboard accelerator.
| |
- |
| |
- | <source lang="cpp">
| |
- | file = gtk_menu_item_new_with_mnemonic("_File");
| |
- | </source>
| |
- |
| |
- | To create a mnemonic, we call the <b>gtk_menu_item_new_with_mnemonic()</b> funtion.
| |
- | We select the file menu item by pressing the Alt + F.
| |
- |
| |
- | <source lang="cpp">
| |
- | new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
| |
- | open = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
| |
- |
| |
- | </source>
| |
- |
| |
- | Here we create two image menu items. By setting the second parameter of the function to NULL, we automatically create accelerators.
| |
- | We provide an image and text for our menu item from internal GTK+ resources.
| |
- |
| |
- | <source lang="cpp">
| |
- | sep = gtk_separator_menu_item_new();
| |
- | </source>
| |
- |
| |
- | Menu items can be separated by a horizontal separator. This way we can put menu items into some logical groups.
| |
- |
| |
- | [[image: gtk_faq_menu.png | center]]
| |
- |
| |
- | == Check menu item ==
| |
- |
| |
- | A <b>GtkCheckMenuItem</b> is a menu item with a check box.
| |
- |
| |
- | <source lang="cpp">
| |
- | #include <gtk/gtk.h>
| |
- |
| |
- | void toggle_statusbar(GtkWidget *widget, gpointer statusbar)
| |
- | {
| |
- | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
| |
- | gtk_widget_show(statusbar);
| |
- | } else {
| |
- | gtk_widget_hide(statusbar);
| |
- | }
| |
- | }
| |
- |
| |
- |
| |
- | int main( int argc, char *argv[])
| |
- | {
| |
- |
| |
- | GtkWidget *window;
| |
- | GtkWidget *vbox;
| |
- |
| |
- | GtkWidget *menubar;
| |
- | GtkWidget *viewmenu;
| |
- | GtkWidget *view;
| |
- | GtkWidget *tog_stat;
| |
- | 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), 250, 200);
| |
- | gtk_window_set_title(GTK_WINDOW(window), "view statusbar");
| |
- |
| |
- | vbox = gtk_vbox_new(FALSE, 0);
| |
- | gtk_container_add(GTK_CONTAINER(window), vbox);
| |
- |
| |
- | menubar = gtk_menu_bar_new();
| |
- | viewmenu = gtk_menu_new();
| |
- |
| |
- | view = gtk_menu_item_new_with_label("View");
| |
- | tog_stat = gtk_check_menu_item_new_with_label("View Statusbar");
| |
- | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tog_stat), TRUE);
| |
- |
| |
- | gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), viewmenu);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(viewmenu), tog_stat);
| |
- | gtk_menu_shell_append(GTK_MENU_SHELL(menubar), view);
| |
- | gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);
| |
- |
| |
- | statusbar = gtk_statusbar_new();
| |
- | gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 1);
| |
- |
| |
- | g_signal_connect_swapped(G_OBJECT(window), "destroy",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | g_signal_connect(G_OBJECT(tog_stat), "activate",
| |
- | G_CALLBACK(toggle_statusbar), statusbar);
| |
- |
| |
- | gtk_widget_show_all(window);
| |
- |
| |
- | gtk_main();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- |
| |
- | In our code example we show a check menu item. If the check box is activated, the statusbar widget is shown. If not, the statusbar is hidden.
| |
- |
| |
- | <source lang="cpp">
| |
- | tog_stat = gtk_check_menu_item_new_with_label("View Statusbar");
| |
- | </source>
| |
- |
| |
- | The <b>gtk_check_menu_item_new_with_label()</b> function call creates a new check menu item.
| |
- |
| |
- | <source lang="cpp">
| |
- | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
| |
- | gtk_widget_show(statusbar);
| |
- | } else {
| |
- | gtk_widget_hide(statusbar);
| |
- | }
| |
- | </source>
| |
- |
| |
- | If the check box in the menu item is activated, we show the statusbar widget. Otherwise the statusbar is hidden.
| |
- |
| |
- | [[image: gtk_faq_checkmenuitem.png | center]]
| |
- |
| |
- | == A toolbar ==
| |
- |
| |
- | Menus group commands that we can use in application. Toolbars provide a quick access to the most frequently used commands.
| |
- |
| |
- | <source lang="cpp">
| |
- | #include <gtk/gtk.h>
| |
- |
| |
- | int main( int argc, char *argv[])
| |
- | {
| |
- |
| |
- | GtkWidget *window;
| |
- | GtkWidget *vbox;
| |
- |
| |
- | GtkWidget *toolbar;
| |
- | GtkToolItem *new;
| |
- | GtkToolItem *open;
| |
- | GtkToolItem *save;
| |
- | GtkToolItem *sep;
| |
- | GtkToolItem *exit;
| |
- |
| |
- |
| |
- | 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), 250, 200);
| |
- | gtk_window_set_title(GTK_WINDOW(window), "toolbar");
| |
- |
| |
- | vbox = gtk_vbox_new(FALSE, 0);
| |
- | gtk_container_add(GTK_CONTAINER(window), vbox);
| |
- |
| |
- |
| |
- | toolbar = gtk_toolbar_new();
| |
- | gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
| |
- |
| |
- | gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
| |
- |
| |
- | new = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new, -1);
| |
- |
| |
- | open = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open, -1);
| |
- |
| |
- | save = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save, -1);
| |
- |
| |
- | sep = gtk_separator_tool_item_new();
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
| |
- |
| |
- | exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
| |
- |
| |
- | gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
| |
- |
| |
- | g_signal_connect(G_OBJECT(exit), "clicked",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | g_signal_connect_swapped(G_OBJECT(window), "destroy",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | gtk_widget_show_all(window);
| |
- |
| |
- | gtk_main();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- |
| |
- | The code example creates simple toolbar example.
| |
- |
| |
- | <source lang="cpp">
| |
- | toolbar = gtk_toolbar_new();
| |
- | gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS)
| |
- | </source>
| |
- |
| |
- | We create a new toolbar. We specify that the toobar buttons show only icons. No text.
| |
- |
| |
- | <source lang="cpp">
| |
- | new = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new, -1);
| |
- | </source>
| |
- |
| |
- | We create a toolbar button from stock. The toolbar buttons are inserted into the toolbar by the <b>gtk_toolbar_insert()</b> function call.
| |
- |
| |
- | <source lang="cpp">
| |
- | sep = gtk_separator_tool_item_new();
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
| |
- | </source>
| |
- |
| |
- | Here we insert a separator into the toolbar.
| |
- |
| |
- | [[image: gtk_faq_toolbar.png | center]]
| |
- |
| |
- | == Undo redo ==
| |
- |
| |
- | The following example demonstrates, how we can inactivate toolbar buttons on the toolbar. It is a common practise in GUI programming. For example the save button. If we save all changes of our document to the disk, the save button is inactivated in most text editors. This way the application indicates to the user, that all changes are already saved.
| |
- |
| |
- | <source lang="cpp">
| |
- | #include <gtk/gtk.h>
| |
- | #include <string.h>
| |
- |
| |
- | void undo_redo(GtkWidget *widget, gpointer item)
| |
- | {
| |
- | static int count = 2;
| |
- | const char *name = gtk_widget_get_name(widget);
| |
- |
| |
- | if ( strcmp(name, "undo") ) {
| |
- | count++;
| |
- | } else {
| |
- | count--;
| |
- | }
| |
- |
| |
- | if (count < 0) {
| |
- | gtk_widget_set_sensitive(widget, FALSE);
| |
- | gtk_widget_set_sensitive(item, TRUE);
| |
- | }
| |
- |
| |
- | if (count > 5) {
| |
- | gtk_widget_set_sensitive(widget, FALSE);
| |
- | gtk_widget_set_sensitive(item, TRUE);
| |
- | }
| |
- | }
| |
- |
| |
- |
| |
- | int main( int argc, char *argv[])
| |
- | {
| |
- |
| |
- | GtkWidget *window;
| |
- | GtkWidget *vbox;
| |
- |
| |
- | GtkWidget *toolbar;
| |
- | GtkToolItem *undo;
| |
- | GtkToolItem *redo;
| |
- | GtkToolItem *sep;
| |
- | GtkToolItem *exit;
| |
- |
| |
- |
| |
- | 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), 250, 200);
| |
- | gtk_window_set_title(GTK_WINDOW(window), "undoredo");
| |
- |
| |
- | vbox = gtk_vbox_new(FALSE, 0);
| |
- | gtk_container_add(GTK_CONTAINER(window), vbox);
| |
- |
| |
- |
| |
- | toolbar = gtk_toolbar_new();
| |
- | gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
| |
- |
| |
- | gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
| |
- |
| |
- | undo = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
| |
- | gtk_widget_set_name(GTK_WIDGET(undo), "undo");
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1);
| |
- |
| |
- | redo = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), redo, -1);
| |
- |
| |
- | sep = gtk_separator_tool_item_new();
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
| |
- |
| |
- | exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
| |
- | gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
| |
- |
| |
- | gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
| |
- |
| |
- |
| |
- | g_signal_connect(G_OBJECT(undo), "clicked",
| |
- | G_CALLBACK(undo_redo), redo);
| |
- |
| |
- | g_signal_connect(G_OBJECT(redo), "clicked",
| |
- | G_CALLBACK(undo_redo), undo);
| |
- |
| |
- | g_signal_connect(G_OBJECT(exit), "clicked",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | g_signal_connect_swapped(G_OBJECT(window), "destroy",
| |
- | G_CALLBACK(gtk_main_quit), NULL);
| |
- |
| |
- | gtk_widget_show_all(window);
| |
- |
| |
- | gtk_main();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- |
| |
- | Our example creates undo and redo buttons from the GTK+ stock resources. After several clicks each of the buttons is inactivated. The buttons are grayed out.
| |
- |
| |
- | <source lang="cpp">
| |
- | if (count < 0) {
| |
- | gtk_widget_set_sensitive(widget, FALSE);
| |
- | gtk_widget_set_sensitive(item, TRUE);
| |
- | }
| |
- |
| |
- | if (count > 5) {
| |
- | gtk_widget_set_sensitive(widget, FALSE);
| |
- | gtk_widget_set_sensitive(item, TRUE);
| |
- | }
| |
- | </source>
| |
- |
| |
- | The <b>gtk_widget_set_sensitive()</b> function call is used to activate/inactivate the toolbar buttons.
| |
- |
| |
- | [[image: gtk_faq_undoredo.png | center]]
| |
- |
| |
- | [[Категория:GTK+]]
| |