All user interfaces developed with Perl/Tk follow this general sequence:
Instantiate one or more widgets, configure them, and arrange them inside the main window. A widget is simply a collection of data and methods that produce some visible element of the interface, like a button or listbox, and make it behave properly when clicked or otherwise manipulated.
Start the event loop. After this, the user's actions (events) determine what the program does.
Example 14.1 shows these steps executed in serial order; they result in the simple GUI[3] shown in Figure 14.1.
[3] Though there's nothing interactive about it - nothing much graphical either, actually.
use Tk; # Slurp the module in. # ------------------------------------------------------- # Create a main window # ------------------------------------------------------- $top = MainWindow->new(); $top->title ("Simple"); # ------------------------------------------------------- # Instantiate widgets and arrange them # ------------------------------------------------------- $l = $top->Label(text => 'hello', # label properties anchor => 'n', # anchor text to "north" relief => 'groove', # border style width => 10, height => 3); # 10 chars wide, 3 high. $l->pack(); # Give it a default place within the main window # ------------------------------------------------------- # Sit in an infinite loop dispatching incoming events. # ------------------------------------------------------- MainLoop();
This example captures a number of significant Tk concepts (and those of most GUI toolkits in general).
The main window is the outermost shell and contains the resize handles, system menu, and minimize and maximize boxes (also known as decorations). An application can have any number of main windows.
The main window is then asked to create a label widget with preconfigured properties. You can change your mind about a widget's properties by invoking the configure method on it:
$label->configure (text => 'foobar', foreground => 'red');
Some widgets, such as Frame and Notebook, are themselves capable of containing other widgets, so the widget hierarchy can be arbitrarily nested. A main window is always at the root of the hierarchy.
The widget's pack method is then called to do geometry management: the scheme for allocating the position and the width and height for the widget. This call is simply delegated to the widget's container, the main window, which calculates the amount of screen real estate to apportion to each contained widget. This is akin to saying "socks->pack" and having the suitcase figure out where to put the socks and how much to bunch them up.
Packing is only one of many geometry management schemes available for placing widgets around. Tk supplies a grid geometry manager and a placer ; we'll study both in the section "Geometry Management" later in this chapter.
You can create and pack a widget in one fell swoop, like this:
$l = $top->Label (text => 'Oh my')->pack();
In most cases, you don't even need to capture the return value unless you plan to invoke methods on that widget later. The typical approach is to set up all the parameters at creation time and call MainLoop. We will use this style extensively in this book.
We have already studied the concept of event loops in Chapter 12, and we will have more to say on this topic in the section "Event Loops" later in this chapter. Meanwhile, suffice it to say that MainLoop is an "event dispatcher," which returns only when you close the window by double-clicking on the system menu. It is essential to call this function; otherwise, you'll never see the form on your display. (Incidentally, it is essential to call pack on a widget; otherwise, you'll never see the widget on the display.)
That's all there is to it. Now it is a simple matter of knowing which widgets are available, what properties they support, and how to hook them up together. Read on!
Why write code to create static screens when you can draw them? Stephen Uhler, of the Tcl/Tk team at Sun Microsystems, has written a WYSIWIG GUI builder called SpecTcl (pronounced "spectacle"), with an intention to support multiple languages. This tool has since been customized for Perl/Tk, Java/Tk, and Python/Tk; the resulting variations are called SpecPerl, SpecJava, and SpecPython, respectively. Mark Kvale has done the port for Perl/Tk, and it is available from his home page:[4] http://www.keck.ucsf.edu/~kvale/specPerl/.
[4] Sun has since started selling SpecTcl commercially, so SpecPerl is necessarily dependent on older (and free) SpecTcl code.
Using SpecPerl, you can lay the widgets out visually, set widget-specific properties in corresponding forms, and select colors and fonts from palettes - very convenient.
However, in this chapter (and the next two), we will hand-write GUI code instead of using SpecPerl, for a number of reasons. First, we don't build elaborate forms. Second, most of the examples focus more on the dynamic aspects of Tk, and a GUI builder can only help you build static forms. Third, once you understand this chapter, you'll know what SpecPerl produces.
Copyright © 2001 O'Reilly & Associates. All rights reserved.