Menu creation in GTK+

In this part of the GTK+ programming tutorial, we will work with menus

A menubar 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.

Sample 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.

#include
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;
}

Creating a menubar is a bit confusing. We must bear in mind that both a menubar and menus are derived from the same widget, namely a menu shell. menu items are only valid childs for menus. They are also used to implement submenus

menubar = gtk_menu_bar_new();
filemenu = gtk_menu_new();

In this code we create a menubar and a menu.

gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);

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.

gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);

Menu items are implemented by calling the gtk_menu_shell_append() 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.

g_signal_connect(G_OBJECT(quit), "activate",
G_CALLBACK(gtk_main_quit), NULL);

By selecting the quit menu item, we quit the application.



Figure: Simple menu

Image menus, mnemonics & accelerators

In the next example, we will further explore the functionality that we can use in GTK+. Accelerators are keyboard shortcuts for activating a menu item. Mnemonics are keyboard shortcuts for GUI elements. They are represented as underlined characters.

#include
#include
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;
}

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.

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);

An accelerator group is a group of keyboard accelerators, typically attached to a toplevel window. Here we create Ctrl + q keyboard accelerator.

file = gtk_menu_item_new_with_mnemonic("_File");

To create a mnemonic, we call the gtk_menu_item_new_with_mnemonic() funtion. We select the file menu item by pressing the Alt + F.

new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
open = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);

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.

sep = gtk_separator_menu_item_new();

Menu items can be separated by a horizontal separator. This way we can put menu items into some logical groups.



Figure: Menu example

Check menu item

A GtkCheckMenuItem is a menu item with a check box.

#include
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;
}

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.

tog_stat = gtk_check_menu_item_new_with_label("View Statusbar");
The gtk_check_menu_item_new_with_label() function call creates a new check menu item.
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
gtk_widget_show(statusbar);
} else {
gtk_widget_hide(statusbar);
}

If the check box in the menu item is activated, we show the statusbar widget. Otherwise the statusbar is hidden.

No comments:

 
Top Blogs