Create rich user interfaces in Perl
Perl is one of the most popular languages out there, and is used for everything from mission-critical projects to Web applications to "glue." It is not, however, often used for GUI programming and prototyping. Philipp K. Janert thinks it should be, and you probably will too -- after this look at some of the more complex widgets available for Perl/Tk.
In contrast to the widespread use of the Perl language, Perl's GUI toolset, Perl/Tk, is much less popular. This is strange, because it is arguably one of the easiest GUI toolkits to program (at least for UNIX platforms), and therefore suggests itself for user interface prototyping or for quickly providing a user-friendly wrapper around cryptic command-line tools.
One reason for this relative indifference toward Perl/Tk appears to be the perception that it is not very powerful and does not lend itself to sophisticated applications. However, a number of widgets that provide more complex functionality are available as user contributions on CPAN. In this article, I will take a look at some of them and show how they can be used to create a richer user experience. I will also point out some more generally useful techniques for programming with Perl/Tk.
(The other problem with Perl/Tk, of course is, that its widgets look ugly and are not "theme-able." Unfortunately, I cannot do anything about that.)
Prerequisites and availability
A good knowledge of Perl and at least rudimentary experience with Perl/Tk as well as general GUI programming concepts -- events, widgets, callbacks, geometry managers -- are assumed throughout. You can find introductory resources on Perl/Tk in the Resources section of this article.
You can freely download all the widgets discussed in this article from CPAN, the Comprehensive Perl Archive Network. Most have many more options than can be explained here: the perldoc for each widget and -- in some cases -- the source code, provide the ultimate and complete reference.
Tabbed frames: Tk::NoteBook
A common GUI widget, the Tab helps to group a large number of options into smaller subsets and so add structure to, for instance, complicated dialog boxes.
A widget with Tab-like appearance and semantics for Perl/Tk is
Tk::NoteBook
. An example, using three tabs,
is shown in Figure 1. Note that the third tab is disabled.
This example was produced by the following code:
Listing 1: Using the NoteBook widget
|
Specifying arguments to callbacks
or as a direct invocation of the callback from within an anonymous subroutine:
The difference between the two methods has to do with variable scoping; more precisely, with the exact time the parameters are evaluated.
In the first case, the parameters are evaluated at the time
that the constructor containing the
In contrast, the contents of the anonymous subroutine used in
the second case are not evaluated until this subroutine is
actually invoked. In other words, the callback sees the
values of the parameters at the time the callback is
executed. This is important in the
Finally, because the body of the |
As in any Perl/Tk application, we first specify the modules
we are going to use and then create a MainWindow
. Note that Tk::NoteBook
, as well as the other
contributed widgets on CPAN, are not part of the standard Tk
distribution, and therefore need to be specified explicitly.
We create a NoteBook
widget as child to the
MainWindow
and then add three tabs. The
first
argument to the add()
function is a symbolic
name, by which the generated page can be referred to in the
notebook: we will make use of it below.
I should make two comments on geometry management when using the
NoteBook
widget. First, although the
tabs are widgets themselves, they do not need to be pack
ed. Their geometry management is
handled by the enclosing NoteBook
. Second, if the parent window of
the NoteBook
widget is resizable, it
is important to specify both the -fill
and the -expand
attributes when pack
ing the NoteBook
. The latter will make sure that
the NoteBook
's allocation rectangle
will always expand to fill the available space, while the former
ensures that the actual NoteBook
widget will expand to fill its allocation rectangle.
The tabs accept a variety of attributes. Here we demonstrate
-createcmd
, -raisecmd
, and -state
. The first two can be used to
register callbacks, which will be invoked when the tab is first
created and whenever it is raised, respectively; while the last
one can take on the values normal
and disabled
. We also use the -raisecmd
callback on the second tab to
switch the third tab from its disabled to its active state once
the second tab has been raised for the first time. We do this
using the pageconfigure()
function on
the enclosing NoteBook
widget,
passing the symbolic name of the referenced tab as the first
argument.
Versatile graphical display: Tk::ProgressBar
The Tk::ProgressBar
is a widget that
displays a graphical representation of a scalar value. Progress
bars are commonly used to provide feedback to the user when
downloading large files or
performing similar long-running tasks. The
corresponding widget in Perl/Tk offers some special features
that can make it attractive for other uses as well.
Figure 2. The ProgressBar widget
This example contains two ProgressBar
widgets, coupled to a standard Scale
. Moving the slider changes the length
of the displayed color bar by invoking the callback named fct
, which calls the value
function on the ProgressBar
s to set the new length. A value
of 100
corresponds to the full length
of the visible color bar. This value can be changed, as can be
the value corresponding to a zero-length color bar, using the
-to
and -from
attributes, respectively.
Listing 2 demonstrates some of the ways the appearance
of the color bar can be customized. The bottom ProgressBar
is broken into ten blocks, which
are separated by from one another by one-pixel gaps. These are the
default values; they can be set by explicitly specifying values for
the blocks
and gap
attributes. Some experimentation with
the -padx
, -pady
, -length
,
and -borderwidth
attributes is
generally required.
The -colors
attribute accepts a
reference to an array containing pairs of positions and colors.
(Note that the positions must be sorted in ascending order!) The last
specified color will be used for the color bar, until the next
position is reached, at which point the color changes. So,
defining @colors = ( 0, "red", 50, "green" );
yields a color bar that is red on the left
side and green on the other. Here, I provide 100 distinct
values, spanning the colors of the rainbow for the top ProgressBar
. Note that the top ProgressBar
changes its length when the
window is resized.
ProgressBar
widget
|
We specify the callback for the Scale
widget not in its constructor, but later, using the configure
function. The reason is that we
need references to both ProgressBar
s
as arguments to the callback, and at the time the Scale
constructor is invoked, they are not
all defined yet. Changing the order in which the widget
constructors are called is not possible, since this would change
the order in which the widgets are packed.
This code also demonstrates one way to specify arguments to a callback: as an anonymous list, with a reference to the callback invoked as the first element, followed by the required parameters. If a callback does not require arguments, we do not need to create the anonymous list, since Perl treats scalar values, evaluated in list context, as single-element arrays. (For more information on lists in Perl, see Learning Perl, 2nd edition, listed in Resources.) We will encounter a different method for sending parameters to a callback below; check the Sidebar for a discussion of the differences between the two methods.
The freedom to choose arbitrary colors for any segment of the
color bar makes the ProgressBar
interesting for uses as a general display widget: for instance, the
colors can
be used to indicate whether the displayed variable is within the
"normal" parameter range or not. Unfortunately, the widget does
not support an -orient
attribute;
ProgressBar
s are always oriented
horizontally.
View Using advanced widgets in Perl/Tk Discussion
Page: 1 2 3 Next Page: Simplified data entry: Tk::DateEntry and Tk::PathEntry