Enough history. The remainder of this chapter is about the basics of using Perl/Tk, including how to create simple widgets and display them, a quick introduction to event-based programming, and an obligatory “Hello World” example. Before we continue, let’s make sure you have everything installed properly.
Since the Tk extension to Perl doesn’t come with the standard Perl distribution, the first thing you should do is make sure you have a working Perl/Tk distribution.
Whether you’re running Unix or Win32, the perl program should be in your path. Type the following at a command prompt to make the determination:
%
perl -v
If you receive a “command not found” error message, see Appendix A and install Perl. If perl is found, you’ll see output similar to this:
This is perl, v5.6.0 built for i686-linux Copyright 1987-2000, Larry Wall Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5.0 source kit. Complete documentation for Perl, including FAQ lists, should be found on this system using `man perl' or `perldoc perl'. If you have access to the Internet, point your browser at http://www.perl.com/, the Perl Home Page.
In particular, note the version number in the first line; anything earlier than 5.6.0 may not produce the results depicted in this book. Perl 5.005_03 may work, but nothing earlier will, guaranteed.
Now determine if the Tk module is available by using this command:
% perl -e "use Tk"
If you don’t get the following error, you’re ready to go:
Can't locate Tk.pm in @INC (@INC contains: C:\PERL\lib\site ...
Once again, to install Tk refer to Appendix A.
Assuming that Perl/Tk is up and running, you can determine its version with this command:
% perl -MTk -e 'print "$Tk::VERSION\n"'
800.022
Ideally, you want Version 800.022 or higher.
The best way to verify that all is well is
to run the widget demonstration program.
widget should already be in your path, so just
invoke the command by typing widget
at a
command prompt. This program demonstrates most of the Perl/Tk widget
set and lets you examine the Perl/Tk code, modify it, and rerun
individual demonstrations. Clicking on About shows you the installed
Perl and Tk versions.
All widgets in Perl/Tk programs are created in the same basic fashion, with a few exceptions. Each widget must have a parent widget to watch over it as it is created and keep track of it while it exists in the application. When you create an application, you’ll have a central window that will contain other widgets. Usually that window will be the parent of all the widgets inside it and of any other windows you create in your application. You are creating an order to the widgets so that the communication between child and parent widgets can happen automatically without any intervention from you once you set it all up.
Assuming
that the $parent
widget already exists, the
generic usage when you create widget Widgettype
is
as follows:
$child = $parent->Widgettype( [ -option => value, . . . ]
);
Note
that the variables that store the widgets are scalars. (Actually,
they are references to widget objects, but you don’t need to
know that right now.) If you aren’t familiar with
object-oriented syntax in Perl, using the ->
between $parent
and Widgettype
invokes the method Widgettype
from the
$parent
object. It makes the
$parent
related to the child
$child
. As you might guess, the
$parent
becomes the parent of the widget being
created. A parent can have many children, but a child can have only
one parent.
When you invoke the
Widgettype
method, you usually specify
configuration parameters to set up the widget and the interactions
within the application. The configuration parameters will occur in
pairs: an option (such as -text
,
-state
, or -variable)
and its
associated value. Each option starts with a dash, but that’s
only by convention; the options are just strings used to indicate how
to interpret their associated values.
Usually, it is not necessary to put quotation marks around option names because Perl is smart enough to recognize them as strings. However, if you are using the -w switch, Perl may complain about an option that it thinks is not text. You can stick quotes around all your options all the time to avoid this, but it shouldn’t be necessary. The option names are all lowercase, except in a few rare cases that we’ll note as we cover them.
Options are specified in list form:
(-option
=>value
,-option
=>value
,-option
=>value
)
If you’ve never seen
=>
in Perl before, don’t be thrown by it.
It’s just a different way of saying “comma,” except
that the =>
operator auto-quotes the word to
its left, eliminating possible ambiguities. For instance, the
following code works properly because the auto-quoting resolves
-text
as a string:
sub text {} $mw->Label(-text => 123);
With the comma syntax, however, -text
resolves to
-&text( )
:
$mw->Label(-text, 123);
With this in mind, you can still use just the commas and not the
=>
notation, such as:
(-option
,value
,-option
,value
,-option
,value
)
However, it’s much harder to tell which are the option/value pairs. Consider the following syntactically equal statements (each of which create a Button widget that is 10 by 10 pixels, displays the word “Exit,” and performs the action of quitting the application when pressed):
$bttn = $parent->Button(-text, "Exit", -command, sub { exit }, -width, 10, -height, 10); $bttn = $parent->Button(-text => "Exit", -command => sub { exit }, -width => 10, -height => 10);
In the second line, it is much more obvious which arguments are
paired together. The option must be directly before the value
associated with it: -text
is paired with
“Exit”, -command
has the value
sub { exit
}
, and -width
and
-height
both have values of 10.
Another favorite option/value
specification syntax uses Perl’s qw
operator, which treats its arguments as a list of strings:
$bttn = $parent->Button(qw/-text Exit -width 10 -height 10 -command/ => sub { exit }/);
This style is more reminiscent of
Tcl’s look, with whitespace-separated tokens. You tend to type
fewer characters too. The string delimiter is often (
)
or {}
, but //
is
most popular since it doesn’t require a shift. Note that
qw
splits on simple words, so that option values
can be only simple words, not multiword quoted strings, code
references, and so on. That’s why we moved the
-command
option to the end of the
qw
string.
Time for another detour. In the next few chapters we’ll be using widgets in our examples that we might not have covered yet. We trust that you’ll figure out what most of them mean from the context in which they are presented, but a few require a short introduction.
MainWindow and Toplevel are the windows (or widgets—we often interchange the terms) that contain other widgets. MainWindow is a special version of a Toplevel widget, in that the MainWindow is the first window you create in your application.
The other type of widget you need to know about is a Frame widget. A Frame is a container that can also contain other widgets. It is usually invisible and is used just to arrange the widgets as desired.
Of course, there’s more to it, but that’s enough to know for now. For more information, see Chapter 11.
Creating a
widget isn’t the same as displaying it in Perl/Tk. You need to
use two separate commands to create a widget and display it, although
sometimes they are combined into the same line and look like a single
command. In the examples so far, we’ve used the
Button
method to create the Button, but nothing is
displayed by using that method alone. Instead you have to use a
geometry manager to cause the widget to be displayed in its parent
widget or in another widget. The most commonly used geometry manager
is pack
. To use it, you simply call the
pack
method on the widget object, as follows:
$widget->pack( );
For example:
$button->pack( );
The arguments you can send to the pack
method are
covered in Chapter 2.
It is not necessary to invoke the pack
method on a
separate line. ->pack
can be added to the
creation of the widget:
$parent->Button(-text => "Bye!", -command => sub { exit })->pack( );
The other geometry managers available
are grid
, form
, and
place
. All four behave differently; use what works
best for your application. Again, look for information on the
geometry managers in Chapter 2.
When programming an application that uses a graphical interface rather than a textual interface, you need to rethink the way you approach the flow of the application. In a text-based application, you can read from standard input (STDIN), use command-line options, read files, or prompt the user for specific information. The keyboard is your main avenue of input from the user. In a GUI, input comes not only from those places but also from the mouse and the window manager.[5] Although this extra input allows more flexibility in our applications, it also makes our programming job more difficult. As long as we tell it what to do, Perl/Tk helps us handle all that extra input gracefully.
Input in a GUI is defined by events. Events are typically different combinations of using the keyboard and mouse at the same, or different, times. If the user pushes the left mouse button on Button “B,” that is one type of event. Pushing the right mouse button on Button “C” is another event. Typing the letter “a” is another event. Holding down the Control key and clicking with the middle mouse button is yet another event. Events can also come from input and output operations or be generated virtually under program control. For an in-depth examination of the Tk event loop, see Chapter 15.
Events are processed during an event loop. The event loop, as its name implies, handles events during a loop. It determines what subroutines to call based on what type of event has happened. Here is a pseudocode event loop:
while (1) { get_event_info if event is left-mouse-click call process_left_mouse_click else if event is right-mouse-click call process_right_mouse_click else if event is keyboard-input call type_it else handle events for redrawing, resizing etc }
This is obviously a simplistic approach to an event loop, yet it
shows the basic idea. The event loop is a weeding-out process to
determine what type of input has been given to the application. For
example, the subroutine process_left_mouse_click
might determine where the pointer was when the mouseclick occurred
and then call other subroutines based on that information.
In Perl/Tk, the event loop is initiated
by calling a routine called MainLoop
. Anything
prior to this statement is just setting up the interface. Any code
after this call will not execute until after the GUI has exited using
$mw->destroy
.[6]
If we forget to include the MainLoop
statement,
the program will think about things for a while and then go right
back to the command prompt. None of the windows, Buttons, or widgets
will be drawn at all. The first things that occur after calling
MainLoop
are the interface is drawn and the event
loop is started.
Before we get too much further into the event loop and what it does (and what you need to do so it works properly), let’s look at a working example program, Hello World. (You were expecting something else?)
Get Mastering Perl/Tk now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.