You'll almost always create Button widgets with the -command option. This is because for the Button to do something when pressed, we have to associate a callback with the Button. A callback (see Chapter 15, "Anatomy of the MainLoop") is actually a Perl subroutine that's invoked when mouse button 1 is released over the Button.[12] (Note that we specified released; if you click down on the Button but move the cursor away from it before releasing, nothing happens, because the mouseclick was aborted.)
[12] Mouse button 1 is the leftmost mouse button, mouse button 2 is the middle mouse button, and mouse button 3 is the rightmost mouse button. On a 2-button mouse, mouse button 2 is often simulated by pressing buttons 1 and 3 simultaneously.
The simplest way to specify a -command callback is using a code reference. In many of our examples, we use an anonymous code reference to a subroutine that simply executes an exit statement:
$mw->Button(-text => "Done", -command => sub { exit })->pack;
We might also reference an explicit subroutine (that can then be called from multiple places):
$mw->Button(-text => "Done", -command => \&save_and_exit)->pack;
Note that in both examples, -command expects a reference to some Perl code. There are other callback formats, fully explained in Chapter 15, "Anatomy of the MainLoop".
Whereas Button widgets are nearly useless without callbacks, Checkbutton and Radiobutton widgets are designed to change the value of variables. Often, no immediate action is necessary: when a Checkbutton or Radiobutton is toggled, the value of a variable is changed, and then the widget simply waits until the user tells it to do something about it. However, sometimes we do want immediate results, as in the previous Radiobutton example.
One thing a Checkbutton might do immediately when clicked is alter the appearance of the window. The Checkbutton might look something like the one in Figure 4-13.
When the user clicks the Checkbutton to turn it on, the window changes to look like Figure 4-14.
Here's the code that makes the magic happen:
#!/usr/bin/perl -w use Tk; $mw = MainWindow->new; $mw->title("Checkbutton"); ## Create other widgets, but don't pack them yet! for ($i = 1; $i <= 5; $i++) { push (@buttons, $mw->Button(-text => "Button$i")); } $mw->Checkbutton(-text => "Show all widgets", -variable => \$cb_value, -command => sub { if ($cb_value) { foreach (@buttons) { $_->pack(-side => 'left'); } } else { foreach (@buttons) { $_->pack('forget'); } } })->pack(-side => 'top'); MainLoop;
To display some widgets later in the program, we create them ahead of time and store references to them in the @buttons array. (Observant readers will notice that the Buttons in this example are rigged just for show and don't even have -command options associated with them. Normally, each would have a specific task to perform when pressed.)
Then we create our Checkbutton. When the Button is clicked (regardless of the status of its indicator), it will call the subroutine pointed to by -command. Our subroutine looks at the current value of $cb_value, shows the Buttons if it is on, and hides them if it is off. The value in $cb_value is changed before this subroutine is called. When our Checkbutton is clicked again, the extra Buttons will be removed from the window and the window will shrink back to its previous size.
This setup is great when you want to keep a basic window uncluttered while maintaining the ability to show more widgets (if the user can handle the advanced functions of the extra widgets). For example, you can create a Find window that has a place to enter text, a Button to start the find, and an Advanced Search Checkbutton. Clicking on Advanced Search would add more widgets to the bottom of the window, allowing you to match case, use regular expressions, and use other fancy search mechanisms.
Copyright © 2002 O'Reilly & Associates. All rights reserved.