Chapter 16. Menus

Objective

As soon as you create more complex programs, the use of menus become almost compulsory. This lesson will discuss how to create menus.

16.1. Background

Both Gtk2::Menu and Gtk2::MenuBar are subclasses of Gtk2::MenuShell. You can not create a Gtk2::MenuShell directly. You create either a Gtk2::Menu, or a Gtk2::MenuBar, or both, to help create the structure of your menus. This will give you acces the methods of Gtk2::MenuShell.

You pack Gtk2::MenuItem's into a Gtk2::Menu and a Gtk2::MenuBar. There are different kinds of Gtk2::MenuItems. They include the following:

Table 16-1. Available menu items

Gtk2 Class NameUse
Gtk2::MenuItemStandard menu item, may include a mnemonic to include the Alt shortcut. This is the base class from which all subsequent menuitems in this list gets derived.
Gtk2::CheckMenuItemThis is the equivalent of a Gtk2::ToggleButton. It can be set active or not.
Gtk2::RadioMenuItemThis is the equivalent of a Gtk2::RadioButton. When it gets created, you define a group to which it belongs. At any given instance, only one Gtk2::RadioMenuItem belonging to this group can be selected.
Gtk2::ImageMenuItemTo give your application that extra elegance, you can use this. It can be used to pack an image in front of the menu's label.
Gtk2::SeparatorMenuItemThis is the equivalent of a Gtk2::HSeparator. It us used to give logical grouping to menu items.
Gtk2::TearoffMenuItemAdding this to Gtk2::Menu, will enable you to separate this menu from its parent menu.

We will create a demo program which incorporates all of these menu items, so you can see them in action. The demo program will also feature a popup menu. This type of menu does not require a Gtk2::MenuBar and usually gets displayed when the right mouse button is clicked.

Creating basic menus.

16.1.1. The Screenshot.

Figure 16-1. Basic Menu

16.1.2. The Code.

The program can be found here: 'gtk2_menu_basic.pl'

  1 #! /usr/bin/perl -w
  2 
  3 use strict;
  4 use Gtk2 '-init';
  5 use Glib qw/TRUE FALSE/; 
  6 
  7 #standard window creation, placement, and signal connecting
  8 my $window = Gtk2::Window->new('toplevel');
  9 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; });
 10 $window->set_border_width(5);
 11 $window->set_position('center_always');
 12 
 13 #this vbox will return the bulk of the gui
 14 my $vbox = &ret_vbox();
 15 
 16 #add and show the vbox
 17 $window->add($vbox);
 18 $window->show();
 19 
 20 #our main event-loop
 21 Gtk2->main();
 22 
 23 sub ret_vbox {
 24 
 25 my $vbox = Gtk2::VBox->new(FALSE,5);
 26 $vbox->set_size_request (300, 300);
 27 
 28 	#====================================
 29 	#Start of with a Gtk2::Menu widget
 30 	my $menu_edit = Gtk2::Menu->new();
 31 	
 32 	#--------
 33 	#add a tearoff item
 34 	$menu_edit->append(Gtk2::TearoffMenuItem->new);
 35 	
 36 	#________
 37 	#add an Image Menu item using stock
 38 		my $menu_item_cut = Gtk2::ImageMenuItem->new_from_stock ('gtk-cut', undef);
 39 		#connet to the activate signal to catch when this item is selected
 40 		$menu_item_cut->signal_connect('activate' => sub { print "selected the cut menu\n"});
 41 	$menu_edit->append($menu_item_cut);
 42 	
 43 	#_________
 44 	#add a separator
 45 	$menu_edit->append(Gtk2::SeparatorMenuItem->new());
 46 	
 47 	#_________
 48 	#add a check menu item	
 49 		my $menu_item_toggle = Gtk2::CheckMenuItem->new('_Toggle Menu Item');
 50 		#connect to the toggled signal to catch the active state
 51 		$menu_item_toggle->signal_connect('toggled' => \&toggle,"Toggle Menu Item");
 52 	$menu_edit->append($menu_item_toggle);
 53 	
 54 	#_________
 55 	#add a separator
 56 	$menu_edit->append(Gtk2::SeparatorMenuItem->new());
 57 	
 58 	#_________
 59 	#add radio menu items	
 60 		my $menu_radio_one = Gtk2::RadioMenuItem->new(undef,'Radio one');
 61 		#connect to the toggled signal to catch the changes
 62 		$menu_radio_one->signal_connect('toggled' => \&toggle,"Radio one");
 63 		my $group = $menu_radio_one->get_group;
 64 	$menu_edit->append($menu_radio_one);
 65 	
 66 		my $menu_radio_two = Gtk2::RadioMenuItem->new($group, 'Radio two');
 67 		#connect to the toggled signal to catch the changes
 68 		$menu_radio_two->signal_connect('toggled' => \&toggle,"Radio two");
 69 	$menu_edit->append($menu_radio_two);
 70 	
 71 	#_________
 72 	#add a separator
 73 	$menu_edit->append(Gtk2::SeparatorMenuItem->new());
 74 	
 75 	#_________
 76 	#add an Image Menu Item using an external image
 77 		my $menu_item_image = Gtk2::ImageMenuItem->new ('Image Menu Item');
 78 			my $img = Gtk2::Image->new_from_file('./pix/1.png');
 79 		$menu_item_image->signal_connect('activate' => sub { print "selected the Image Menu Item\n"});
 80 		#connet to the activate signal to catch when this item is selected
 81 		$menu_item_image->set_image($img);
 82 	
 83 	$menu_edit->append($menu_item_image);
 84 	#====================================
 85 	
 86 	#create a menu bar with two menu items, one will have $menu_edit
 87 	#as a submenu		
 88 	my $menu_bar = Gtk2::MenuBar->new;
 89 	
 90 	#_________
 91 	#add a menu item
 92 		my $menu_item_edit= Gtk2::MenuItem->new('_Edit');
 93 		#set its sub menu
 94 		$menu_item_edit->set_submenu ($menu_edit);
 95 				
 96 	$menu_bar->append($menu_item_edit);
 97 	
 98 	#_________
 99 	#add a menu item
100 		my $menu_item_help = Gtk2::MenuItem->new('_Help');
101 		$menu_item_help->set_sensitive(FALSE);
102 		#push it off to the right
103 		$menu_item_help->set_right_justified(TRUE);
104 		  
105 	$menu_bar->append($menu_item_help);	
106 
107 $vbox->pack_start($menu_bar,FALSE,FALSE,0);
108 
109 	#====================================
110 	#add an event box to catch the right clicks
111 	my $eventbox = Gtk2::EventBox->new();
112 
113 $eventbox->signal_connect('button-release-event' => sub {
114 	
115 		my ($widget,$event) = @_;		
116 		my $button_nr = $event->button;
117 		#make sure it was the right mouse button				
118 		($button_nr == 3)&&($menu_edit->popup(undef,undef,undef,undef,0,0));
119 		
120 	});
121 
122 $vbox->pack_start($eventbox,TRUE,TRUE,0);
123 $vbox->show_all();
124 return $vbox;
125 }
126 
127 sub toggle {
128 
129 	my ($menu_item,$text) = @_;
130 			my $val = $menu_item->get_active;
131 			($val)&&(print "$text active\n");
132 			($val)||(print "$text not active\n"); 
133 }

16.1.3. Points of interest.

  • A Gtk2::MenuShell contains menu items. In our program we make use of the various types available. The Gtk2::MenuShell has various methods available to insert the menu items in destined places. Consult the man page to discover the one that best fits your needs. In our program we make use of the 'append' method.

  • The demo program uses the two available subclasses of Gtk2::MenuShell. They are Gtk2::Menu and Gtk2::MenuBar. We add menu items to the Gtk2::MenuBar, and then we use the Gtk2::MenuItem's 'set_submenu' to "attach" a Gtk2::Menu to that Gtk2::MenuItem. This will cause the Gtk2::Menu with all its menu items to 'popup' as soon as we click on the menu to which the Gtk2::Menu was "attached".

  • By using the 'set_submenu' method you can build the desired structure of your menus.

  • To be notified when a menu item is selected, we connect to its 'activate' signal.

  • To be notified when the state of a Gtk2::CheckMenuItem and Gtk2::RadioMenuItem changed, we connect to its 'toggled' signal.

  • When you want a menu item to appear on the right hand side of the Gtk2::MenuBar make use of the Gtk2::MenuItem's 'set_right_justified' method.

  • We also use the created Gtk2::Menu to be a "popup" menu, by making use of its 'popup' method. We filter for the right mouse button, to simulate the typical use op a popup menu.

Note

When you need to create and manage large menu structures, make use of Gtk2::UIManager ( Chapter 18 ). This replaces the deprecated Gtk2::ItemFactory.