February 28, 2021
Hot Topics:

Perl/Tk Menus: Past, Present and Future

  • By Steve Lidie
  • Send Email »
  • More Articles »


Figure 3 shows radio-button and checkbutton menu items -- the checkbuttons are in the lower half of the menu.


Figure 3: Button Menus

Both menu items have an indicator on their left that advertises whether they are on or off. A checkbutton's state (whether it's selected or not) is stored in a Perl scalar. Here's a typical checkbutton creation command:

$menu->checkbutton(-label => 'Autosize line',
             -variable => \$autosize,
             -onvalue => 1, -offvalue => 0,
             -underline => 0, -command => \&line);

So Tk sets $autosize to 1 whenever the item is selected, and 0 when it's deselected. The reverse is true as well -- changing the variable to 0 or 1 changes the indicator. Also, the character at label position zero is underlined, and the subroutine &line is called whenever there's a state change.


Radiobuttons select a single item from a list of related items. (If you have a one item list, just use a checkbutton.) Each radiobutton in a group uses the same Perl scalar to store its value, like this:

$menu->radiobutton(-label => '1 point',
          -variable => \$point, -value => 1,
          -underline => 0, -command => \&point);

$menu->radiobutton(-label => '2 point',
          -variable => \$point, -value => 2,
          -underline => 0, -command => \&point);

The scalar $point takes on one of several point sizes as the radiobutton indicators are clicked. And like checkbuttons, changing the variable's value changes the Tk indicator, and invokes a callback.

Tk 4 Menubars

Many Perl/Tk programs manually build their menubars by packing menubuttons into a frame. Some buttons are left-justified, some are right-justified. The following statements are from program menubar1, and produce a menubar identical to what you see in Figure 4.

Figure 4
Figure 4

my $mw = MainWindow->new;
my $menubar = $mw->Frame(qw/-relief raised -borderwidth 2/);
$menubar->pack(qw/-fill x/);

my $file = $menubar->Menubutton(qw/-text File-underline 0/);
my $cas1 = $menubar->Menubutton(qw/-text Cascades-underline 3/);
my $help = $menubar->Menubutton(qw/-text Help -underline 0/);

$file->pack(qw/-side left/);
$cas1->pack(qw/-side left/);
$help->pack(qw/-side right/);

Thus far I've intentionally avoided cascades; it's time to remedy that situation by adding one (keep Figure 4 in mind). I've found that almost no one grasps how to make multi-level cascades, mainly because the sub-menu creation is so obscure.

my $cas2 = $cas1->cascade(-label => "Cascade Level 2");
$cas1->command(-label => 'Level 1');

The Cascades menu now has three menu items, a tearoff, a cascade and a command. The cascade item Cascade level 2 needs its sub-menu created, but the sub-menu must be a child of the Cascades menu. The following code fetches the menu reference for the parent menu, creates the sub-menu, and then configures the new cascade.

my $cas1_menu = $cas1->cget(-menu);
my $cas2_menu = $cas1_menu->Menu;
$cas1->entryconfigure('Cascade Level 2', -menu => $cas2_menu);
$cas2->command(-label => 'Level 2',
               -command => sub {print "Level 2\n"});

That's a lot of work, and we won't go any further with this Tk 4 idiom. Much has changed, as we'll see.

Page 2 of 3

This article was originally published on August 19, 1999

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date