userguide(3)

NAME

perl/Tk - Writing Tk applications in perl5.

DESCRIPTION

This manual page is for beginners. It assumes you know
some perl, and have got perl+Tk running. Please run the
'widget' demo before reading this text; it will teach you
the various widget types supported by Tk.

Some background

Tk GUI programming is event-driven. (This may already be
familiar to you.) In event-driven programs, the main GUI
loop is outside of the user program and inside the GUI
library. This loop will watch all events of interest, and
activate the correct handler procedures to handle these
events. Some of these handler procedures may be user-sup
plied; others will be part of the library.

For a programmer, this means that you're not watching what
is happening; instead, you are requested by the toolkit to
perform actions whenever necessary. So, you're not watch
ing for 'raise window / close window / redraw window'
requests, but you tell the toolkit which routine will han
dle such cases, and the toolkit will call the procedures
when required.

First requirements

Any perl program that uses Tk needs to include "use Tk".
A program should also use "use strict" and the -w switch
to ensure the program is working without common errors.

Any Tk application starts by creating the Tk main window.
You then create items inside the main window, or create
new windows, before starting the mainloop. (You can also
create more items and windows while you're running.) The
items will be shown on the display after you "pack" them;
more info on this later. Then you do a Tk mainloop; this
will start the GUI and handle all events. That's your
application. A trivial one-window example is show below:
#! /usr/bin/perl5 -w
use strict;
use Tk;
my $main = MainWindow->new;
$main->Label(-text => 'Hello, world!')->pack;
$main->Button(-text => 'Quit',
-command => [$main => 'destroy']
)->pack;
MainLoop;
Please run this example. It shows you two items types
also shown in the widget demo; it also shows you how items
are created and packed. Finally, note the typical Tk
style using "-option" => "value" pairs.

Item creation

Tk windows and widgets are hierarchical, i.e. one includes
one or more others. You create the first Tk window using
"MainWindow->new". This returns a window handle, assigned
to $main in the example above. Keep track of the main
handle.

You can use any Tk handle to create sub-items within the
window or widget. This is done by calling the Tk con
structor method on the variable. In the example above,
the "Label" method called from $main creates a label wid
get inside the main window. In the constructor call, you
can specify various options; you can later add or change
options for any widget using the "configure" method, which
takes the same parameters as the constructor. The one
exception to the hierarchical structure is the "Toplevel"
constructor, which creates a new outermost window.

After you create any widget, you must render it by calling
"pack". (This is not entirely true; more info later). If
you do not need to refer to the widget after construction
and packing, call "pack" off the constructor results, as
shown for the label and button in the example above. Note
that the result of the compound call is the result of
"pack", which is a valid Tk handle.

Windows and widgets are deleted by calling "destroy" on
them; this will delete and un-draw the widget and all its
children.

Standard Tk types

Button
Radiobutton
Checkbutton
Listbox
Scrollbar
Entry
Text
Canvas
Frame
Toplevel
Scale
Menu
Menubutton

Variables and callback routines

Most graphical interfaces are used to set up a set of val
ues and conditions, and then perform the appropriate
action. The Tk toolkit is different from your average
text-based prompting or menu driven system in that you do
not collect settings yourself, and decide on an action
based on an input code; instead, you leave these values to
your toolkit and only get them when the action is per
formed.

So, where a traditional text-based system would look like
this: (yes, this is obviously dumb code)
#! /usr/bin/perl5 -w
use strict;
print "Please type a font name0;
my $font = <>; chomp $font;
# Validate font
print "Please type a file name0;
my $filename = <>; chomp $filename;
# Validate filename
print "Type <1> to fax, <2> to print0;
my $option = <>; chomp $option;
if ($option eq 1) {
print "Faxing $filename in font $font0;
} elsif ($option eq 2) {
print "Now sending $filename to printer in
font $font0;
}
The (slightly larger) example below shows how to do this
is Tk. Note the use of callbacks. Note, also, that Tk
handles the values, and the subroutine uses "get" to get
at the values. If a user changes his mind and wants to
change the font again, the application never notices; it's
all handled by Tk.

#! /usr/bin/perl5 -w
use strict;
use Tk;
my $main = MainWindow->new;
$main->Label(-text => 'Print file')->pack;
my $font = $main->Entry(-width => 10);
$font->pack;
my $filename = $main->Entry(-width => 10);
$filename->pack;
$main->Button(-text => 'Fax',
-command => sub{do_fax($filename,
$font)}
)->pack;
$main->Button(-text => 'Print',
-command => sub{do_print($filename,
$font)}
)->pack;
MainLoop;
sub do_fax {
my ($file, $font) = @_;
my $file_val = $file->get;
my $font_val = $font->get;
print "Now faxing $file_val in $font_val0;
}
sub do_print {
my ($file, $font) = @_;
my $file_val = $file->get;
my $font_val = $font->get;
print "Sending file $file_val to printer in
$font_val0;
}

The packer. Grouping and frames.

In the examples above, you must have noticed the pack
calls. This is one of the more complicated parts of Tk.
The basic idea is that any window or widget should be sub
ject to a Tk widget placement manager; the packer is one
of the placement managers.

The actions of the packer are rather simple: when applied
to a widget, the packer positions that widget on the indi
cated position within the remaining space in its parent.
By default, the position is on top; this means the next
items will be put below. You can also specify the left,
right, or bottom positions. Specify position using -side
=> 'right'.

Additional packing parameters specify the behavior of the
widget when there is some space left in the frame or when
the window size is increased. If widgets should maintain
a fixed size, specify nothing; this is the default. For
widgets that you want to fill up the current horizontal
space, specify -fill => 'x', y, or both; for widgets that should grow, specify -expand => 1. These parameters are not shown in the example below; see the widget demo.

If you want to group some items within a window that have
a different packing order than others, you can include
them in a Frame. This is a do-nothing window type that is
meant for packing (and to play games with borders and col
ors).

The example below shows the use of pack and frames:
#! /usr/bin/perl5 -w
use strict;
use Tk;
# Take top, the bottom -> now implicit top is in
the middle
my $main = MainWindow->new;
$main->Label(-text => 'At the top (de
fault)')->pack;
$main->Label(-text => 'At the bottom')->pack(-side
=> 'bottom');
$main->Label(-text => 'The middle remains')->pack;
# Since left and right are taken, bottom will not
work...
my $top1 = $main->Toplevel;
$top1->Label(-text => 'Left')->pack(-side =>
'left');
$top1->Label(-text => 'Right')->pack(-side =>
'right');
$top1->Label(-text => '?Bottom?')->pack(-side =>
'bottom');
# But when you use frames, things work quite al
right
my $top2 = $main->Toplevel;
my $frame = $top2->Frame;
$frame->pack;
$frame->Label(-text => 'Left2')->pack(-side =>
'left');
$frame->Label(-text => 'Right2')->pack(-side =>
'right');
$top2->Label(-text => 'Bottom2')->pack(-side =>
'bottom');
MainLoop;

More than one window

Most real applications require more than one window. As
you read before, you can create more outermost windows by
using Toplevel. Each window is independent; destroying a
toplevel window does not affect the others as long as they
are not a child of the closed toplevel. Exiting the main
window will end the application. The example below shows
a trivial three-window application:
#! /usr/bin/perl5 -w
use strict;
use Tk;
my $main = MainWindow->new;
fill_window($main, 'Main');
my $top1 = $main->Toplevel;
fill_window($top1, 'First top-level');
my $top2 = $main->Toplevel;
fill_window($top2, 'Second top-level');
MainLoop;
sub fill_window {
my ($window, $header) = @_;
$window->Label(-text => $header)->pack;
$window->Button(-text => 'close',
-command => [$window => 'de
stroy']
)->pack(-side => 'left');
$window->Button(-text => 'exit',
-command => [$main => 'de
stroy']
)->pack(-side => 'right');
}

More callbacks

So far, all callback routines shown called a user proce
dure. You can also have a callback routine call another
Tk routine. This is the way that scroll bars are imple
mented: scroll-bars can call a Tk item or a user proce
dure, whenever their position has changed. The Tk item
that has a scrollbar attached calls the scrollbar when its
size or offset has changed. In this way, the items are
linked. You can still ask a scrollbar's position, or set
it by hand - but the defaults will be taken care of.

The example below shows a listbox with a scroll bar. Mov
ing the scrollbar moves the listbox. Scanning a listbox
(dragging an item with the left mouse button) moves the
scrollbar.
#! /usr/bin/perl5 -w
use strict;
use Tk;
my $main = MainWindow->new;
my $box = $main->Listbox(-relief => 'sunken',
-width => -1, # Shrink to
fit
-height => 5,
-setgrid => 1);
my @items = qw(One Two Three Four Five Six Seven
Eight Nine Ten Eleven Twelve);
foreach (@items) {
$box->insert('end', $_);
}
my $scroll = $main->Scrollbar(-command =>
['yview', $box]);
$box->configure(-yscrollcommand => ['set',
$scroll]);
$box->pack(-side => 'left', -fill => 'both', -ex
pand => 1);
$scroll->pack(-side => 'right', -fill => 'y');
MainLoop;

Canvases and tags

One of the most powerful window types in Tk is the Canvas
window. In a canvas window, you can draw simple graphics
and include other widgets. The canvas area may be larger
than the visible window, and may then be scrolled. Any
item you draw on the canvas has its own id, and may
optionally have one or more tags. You may refer to any
item by its id, and may refer to any group of items by a
common tag; you can move, delete, or change groups of
items using these tags, and you can bind actions to tags.
For a properly designed (often structured) canvas, you can
specify powerful actions quite simply.

In the example below, actions are bound to circles (single
click) and blue items (double-click); obviously, this can
be extended to any tag or group of tags.
#! /usr/bin/perl5 -w
use strict;
use Tk;
# Create main window and canvas
my $main = MainWindow->new;
my $canvas = $main->Canvas;
$canvas->pack(-expand => 1, -fill => 'both');
# Create various items
create_item($canvas, 1, 1, 'circle', 'blue',
'Jane');
create_item($canvas, 4, 4, 'circle', 'red', 'Pe
ter');
create_item($canvas, 4, 1, 'square', 'blue',
'James');
create_item($canvas, 1, 4, 'square', 'red', 'Pa
tricia');
# Single-clicking with left on a 'circle' item in
vokes a procedure
$canvas->bind('circle', '<1>' => sub {handle_cir
cle($canvas)});
# Double-clicking with left on a 'blue' item in
vokes a procedure
$canvas->bind('blue', '<Double-1>' => sub {han
dle_blue($canvas)});
MainLoop;
# Create an item; use parameters as tags (this is
not a default!)
sub create_item {
my ($can, $x, $y, $form, $color, $name) = @_;
my $x2 = $x + 1;
my $y2 = $y + 1;
my $kind;
$kind = 'oval' if ($form eq 'circle');
$kind = 'rectangle' if ($form eq 'square');
$can->create(($kind, "$x" . 'c', "$y" . 'c',
"$x2" . 'c', "$y2" . 'c'),
-tags => [$form, $color, $name],
-fill => $color);
}
# This gets the real name (not current, blue/red,
square/circle)
# Note: you'll want to return a list in realistic
situations...
sub get_name {
my ($can) = @_;
my $item = $can->find('withtag', 'current');
my @taglist = $can->gettags($item);
my $name;
foreach (@taglist) {
next if ($_ eq 'current');
next if ($_ eq 'red' or $_ eq 'blue');
next if ($_ eq 'square' or $_ eq 'cir
cle');
$name = $_;
last;
}
return $name;
}
sub handle_circle {
my ($can) = @_;
my $name = get_name($can);
print "Action on circle $name...0;
}
sub handle_blue {
my ($can) = @_;
my $name = get_name($can);
print "Action on blue item $name...0;
}
Copyright © 2010-2025 Platon Technologies, s.r.o.           Index | Man stránky | tLDP | Dokumenty | Utilitky | O projekte
Design by styleshout