Recipe 15.14 Creating Menus with Tk
15.14.1 Problem
You want to create a window
that has a menu bar at the top.
15.14.2 Solution
Use the Tk
Menubutton and Frame widgets:
use Tk;
$main = MainWindow->new( );
# Create a horizontal space at the top of the window for the
# menu to live in.
$menubar = $main->Frame(-relief => "raised",
-borderwidth => 2)
->pack (-anchor => "nw",
-fill => "x");
# Create a button labeled "File" that brings up a menu
$file_menu = $menubar->Menubutton(-text => "File",
-underline => 1)
->pack (-side => "left" );
# Create entries in the "File" menu
$file_menu->command(-label => "Print",
-command => \&Print);
This is considerably easier if you use the
-menuitems shortcut:
$file_menu = $menubar->Menubutton(-text => "File",
-underline => 1,
-menuitems => [
[ Button => "Print",-command => \&Print ],
[ Button => "Save",-command => \&Save ] ])
->pack(-side => "left");
15.14.3 Discussion
Menus in applications can be viewed as four separate components
working together: Frames, Menubuttons, Menus, and Menu Entries. The
Frame is the horizontal bar at the top of the window that the menu
resides in (the menubar). Inside the Frame are a
set of Menubuttons, corresponding to Menus: File, Edit, Format,
Buffers, and so on. When the user clicks on a Menubutton, the
Menubutton brings up the corresponding Menu, a vertically arranged
list of Menu Entries.
Options on a
Menu are labels (Open, for example) or
separators (horizontal lines dividing one set of
entries from another in a single menu).
The command entry,
like Print in the File menu shown earlier, has code associated with
it. When the entry is selected, the command is run by invoking the
callback. These are the most common:
$file_menu->command(-label => "Quit Immediately",
-command => sub { exit } );
Separators don't have any action associated with them:
$file_menu->separator( );
A
checkbutton menu entry has an on value, an off
value, and a variable associated with it. If the variable has the on
value, the checkbutton menu entry has a check beside its label. If
the variable has the off value, it does not. Selecting the entry on
the menu toggles the state of the variable.
$options_menu->checkbutton(-label => "Create Debugging File",
-variable => \$debug,
-onvalue => 1,
-offvalue => 0);
A group of
radiobuttons is associated with a single
variable. Only one radiobutton associated with that variable can be
on at any time. Selecting a radiobutton gives the variable the value
associated with it:
$debug_menu->radiobutton(-label => "Level 1",
-variable => \$log_level,
-value => 1);
$debug_menu->radiobutton(-label => "Level 2",
-variable => \$log_level,
-value => 2);
$debug_menu->radiobutton(-label => "Level 3",
-variable => \$log_level,
-value => 3);
Create nested menus with the
cascade menu entry. For instance, under
Netscape Navigator, the File menu button at the
left has a cascade menu entry New that brings up a selection of new
windows. Creating a cascading menu entry is trickier than creating
the other menu entries. You must create a cascade menu entry, fetch
the new menu associated with that menu entry, and create entries on
that new menu.
# step 1: create the cascading menu entry
$format_menu->cascade (-label => "Font");
# step 2: get the new Menu we just made
$font_menu = $format_menu->cget("-menu");
# step 3: populate that Menu
$font_menu->radiobutton (-label => "Courier",
-variable => \$font_name,
-value => "courier");
$font_menu->radiobutton (-label => "Times Roman",
-variable => \$font_name,
-value => "times");
A
tear-off menu entry lets the user move the menu
that it is on. By default, all Menubuttons and cascade menu entries
make Menus that have a tear-off entry at the top of them. To create
Menus without that default, use the -tearoff
option:
$format_menu = $menubar->Menubutton(-text => "Format",
-underline => 1
-tearoff => 0)
->pack;
$font_menu = $format_menu->cascade(-label => "Font",
-tearoff => 0);
The -menuitems option to
Menubutton is a shorthand for creating these
menubuttons. Pass it an array reference representing the options on
the Menubutton. Each option is itself an anonymous array. The first
two elements of the option array are the button type
("command", "radiobutton",
"checkbutton", "cascade", or
"tearoff") and the menu name.
Here's how to use menuitems to make an Edit menu:
my $f = $menubar->Menubutton(-text => "Edit", -underline => 0,
-menuitems =>
[
[Button => 'Copy', -command => \&edit_copy ],
[Button => 'Cut', -command => \&edit_cut ],
[Button => 'Paste', -command => \&edit_paste ],
[Button => 'Delete', -command => \&edit_delete ],
[Separator => ''],
[Cascade => 'Object ...', -tearoff => 0,
-menuitems => [
[ Button => "Circle", -command => \&edit_circle ],
[ Button => "Square", -command => \&edit_square ],
[ Button => "Point", -command => \&edit_point ] ] ],
])->grid(-row => 0, -column => 0, -sticky => 'w');
15.14.4 See Also
The documentation for the Tk module from CPAN; Mastering
Perl/Tk, by Stephen Lidie and Nancy Walsh
|