home *** CD-ROM | disk | FTP | other *** search
-
- <HTML>
- <HEAD>
- <TITLE>perl/Tk - Writing Tk applications in perl5.</TITLE>
- <LINK REL="stylesheet" HREF="../../../Active.css" TYPE="text/css">
- <LINK REV="made" HREF="mailto:">
- </HEAD>
-
- <BODY>
- <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%>
- <TR><TD CLASS=block VALIGN=MIDDLE WIDTH=100% BGCOLOR="#cccccc">
- <STRONG><P CLASS=block> perl/Tk - Writing Tk applications in perl5.</P></STRONG>
- </TD></TR>
- </TABLE>
-
- <A NAME="__index__"></A>
- <!-- INDEX BEGIN -->
-
- <UL>
-
- <LI><A HREF="#name">NAME</A></LI><LI><A HREF="#supportedplatforms">SUPPORTED PLATFORMS</A></LI>
-
- <LI><A HREF="#description">DESCRIPTION</A></LI>
- <LI><A HREF="#some background">Some background</A></LI>
- <LI><A HREF="#first requirements">First requirements</A></LI>
- <LI><A HREF="#item creation">Item creation</A></LI>
- <LI><A HREF="#standard tk types">Standard Tk types</A></LI>
- <LI><A HREF="#variables and callback routines">Variables and callback routines</A></LI>
- <LI><A HREF="#the packer. grouping and frames.">The packer. Grouping and frames.</A></LI>
- <LI><A HREF="#more than one window">More than one window</A></LI>
- <LI><A HREF="#more callbacks">More callbacks</A></LI>
- <LI><A HREF="#canvases and tags">Canvases and tags</A></LI>
- </UL>
- <!-- INDEX END -->
-
- <HR>
- <P>
- <H1><A NAME="name">NAME</A></H1>
- <P>perl/Tk - Writing Tk applications in perl5.</P>
- <P>
- <HR>
- <H1><A NAME="supportedplatforms">SUPPORTED PLATFORMS</A></H1>
- <UL>
- <LI>Linux</LI>
- <LI>Solaris</LI>
- <LI>Windows</LI>
- </UL>
- <HR>
- <H1><A NAME="description">DESCRIPTION</A></H1>
- <P>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.</P>
- <P>
- <HR>
- <H1><A NAME="some background">Some background</A></H1>
- <P>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-supplied; others will be part
- of the library.</P>
- <P>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 watching for 'raise window / close window / redraw window'
- requests, but you tell the toolkit which routine will handle such cases,
- and the toolkit will call the procedures when required.</P>
- <P>
- <HR>
- <H1><A NAME="first requirements">First requirements</A></H1>
- <P>Any perl program that uses Tk needs to include <CODE>use Tk</CODE>.
- A program should also use <CODE>use strict</CODE> and the <STRONG>-w</STRONG> switch to ensure
- the program is working without common errors.</P>
- <P>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 <A HREF="../../../lib/Pod/perlfunc.html#item_pack"><CODE>pack</CODE></A> 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:</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- my $main = MainWindow->new;
- $main->Label(-text => 'Hello, world!')->pack;
- $main->Button(-text => 'Quit',
- -command => [$main => 'destroy']
- )->pack;
- MainLoop;</PRE>
- <P>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 <CODE>-option</CODE> => <CODE>value</CODE> pairs.</P>
- <P>
- <HR>
- <H1><A NAME="item creation">Item creation</A></H1>
- <P>Tk windows and widgets are hierarchical, i.e. one includes one or more
- others. You create the first Tk window using <CODE>MainWindow->new</CODE>.
- This returns a window handle, assigned to <CODE>$main</CODE> in the example above.
- Keep track of the main handle.</P>
- <P>You can use any Tk handle to create sub-items within the window or widget.
- This is done by calling the Tk constructor method on the variable.
- In the example above, the <CODE>Label</CODE> method called from <CODE>$main</CODE> creates a
- label widget 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 <CODE>configure</CODE> method, which takes the same parameters as the
- constructor.
- The one exception to the hierarchical structure is the <A HREF="#item_Toplevel"><CODE>Toplevel</CODE></A> constructor,
- which creates a new outermost window.</P>
- <P>After you create any widget, you must render it by calling <A HREF="../../../lib/Pod/perlfunc.html#item_pack"><CODE>pack</CODE></A>. (This
- is not entirely true; more info later). If you do not need to refer to
- the widget after construction and packing, call <A HREF="../../../lib/Pod/perlfunc.html#item_pack"><CODE>pack</CODE></A> 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 <A HREF="../../../lib/Pod/perlfunc.html#item_pack"><CODE>pack</CODE></A>,
- which is a valid Tk handle.</P>
- <P>Windows and widgets are deleted by calling <CODE>destroy</CODE> on them;
- this will delete and un-draw the widget and all its children.</P>
- <P>
- <HR>
- <H1><A NAME="standard tk types">Standard Tk types</A></H1>
- <DL>
- <DT><STRONG><A NAME="item_Button">Button</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Radiobutton">Radiobutton</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Checkbutton">Checkbutton</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Listbox">Listbox</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Scrollbar">Scrollbar</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Entry">Entry</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Text">Text</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Canvas">Canvas</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Frame">Frame</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Toplevel">Toplevel</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Scale">Scale</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Menu">Menu</A></STRONG><BR>
- <DD>
- <DT><STRONG><A NAME="item_Menubutton">Menubutton</A></STRONG><BR>
- <DD>
- </DL>
- <P>
- <HR>
- <H1><A NAME="variables and callback routines">Variables and callback routines</A></H1>
- <P>Most graphical interfaces are used to set up a set of values 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 performed.</P>
- <P>So, where a traditional text-based system would look like this:
- (yes, this is obviously dumb code)</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;</PRE>
- <PRE>
- print "Please type a font name\n";
- my $font = <>; chomp $font;
- # Validate font</PRE>
- <PRE>
- print "Please type a file name\n";
- my $filename = <>; chomp $filename;
- # Validate filename</PRE>
- <PRE>
- print "Type <1> to fax, <2> to print\n";
- my $option = <>; chomp $option;
- if ($option eq 1) {
- print "Faxing $filename in font $font\n";
- } elsif ($option eq 2) {
- print "Now sending $filename to printer in font $font\n";
- }</PRE>
- <P>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 <CODE>get</CODE> 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.</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- 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;</PRE>
- <PRE>
- sub do_fax {
- my ($file, $font) = @_;
- my $file_val = $file->get;
- my $font_val = $font->get;
- print "Now faxing $file_val in $font_val\n";
- }</PRE>
- <PRE>
- 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_val\n";
- }</PRE>
- <P>
- <HR>
- <H1><A NAME="the packer. grouping and frames.">The packer. Grouping and frames.</A></H1>
- <P>In the examples above, you must have noticed the <A HREF="../../../site/lib/Tk/pack.html">pack</A> calls.
- This is one of the more complicated parts of Tk. The basic idea
- is that any window or widget should be subject to a Tk widget placement manager;
- the <EM>packer</EM> is one of the placement managers.</P>
- <P>The actions of the packer are rather simple: when applied
- to a widget, the packer positions that widget on the indicated 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 <STRONG>-side => 'right'</STRONG>.</P>
- <P>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 <STRONG>-fill => 'x'</STRONG>, <STRONG>y</STRONG>, or <STRONG>both</STRONG>; for
- widgets that should grow, specify <STRONG>-expand => 1</STRONG>. These
- parameters are not shown in the example below; see the widget demo.</P>
- <P>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 colors).</P>
- <P>The example below shows the use of pack and frames:</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- # Take top, the bottom -> now implicit top is in the middle
- my $main = MainWindow->new;
- $main->Label(-text => 'At the top (default)')->pack;
- $main->Label(-text => 'At the bottom')->pack(-side => 'bottom');
- $main->Label(-text => 'The middle remains')->pack;</PRE>
- <PRE>
- # 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');</PRE>
- <PRE>
- # But when you use frames, things work quite alright
- 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');</PRE>
- <PRE>
- MainLoop;</PRE>
- <P>
- <HR>
- <H1><A NAME="more than one window">More than one window</A></H1>
- <P>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:</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- 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;</PRE>
- <PRE>
- sub fill_window {
- my ($window, $header) = @_;
- $window->Label(-text => $header)->pack;
- $window->Button(-text => 'close',
- -command => [$window => 'destroy']
- )->pack(-side => 'left');
- $window->Button(-text => 'exit',
- -command => [$main => 'destroy']
- )->pack(-side => 'right');
- }</PRE>
- <P>
- <HR>
- <H1><A NAME="more callbacks">More callbacks</A></H1>
- <P>So far, all callback routines shown called a user procedure.
- You can also have a callback routine call another Tk routine.
- This is the way that scroll bars are implemented: scroll-bars
- can call a Tk item or a user procedure, 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.</P>
- <P>The example below shows a listbox with a scroll bar. Moving
- the scrollbar moves the listbox. Scanning a listbox (dragging
- an item with the left mouse button) moves the scrollbar.</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- 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', -expand => 1);
- $scroll->pack(-side => 'right', -fill => 'y');</PRE>
- <PRE>
- MainLoop;</PRE>
- <P>
- <HR>
- <H1><A NAME="canvases and tags">Canvases and tags</A></H1>
- <P>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 <EM>tags</EM>. 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 <EM>bind</EM> actions to tags. For a properly designed (often
- structured) canvas, you can specify powerful actions quite simply.</P>
- <P>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.</P>
- <PRE>
- #! /usr/bin/perl5 -w</PRE>
- <PRE>
- use strict;
- use Tk;</PRE>
- <PRE>
- # Create main window and canvas
- my $main = MainWindow->new;
- my $canvas = $main->Canvas;
- $canvas->pack(-expand => 1, -fill => 'both');</PRE>
- <PRE>
- # Create various items
- create_item($canvas, 1, 1, 'circle', 'blue', 'Jane');
- create_item($canvas, 4, 4, 'circle', 'red', 'Peter');
- create_item($canvas, 4, 1, 'square', 'blue', 'James');
- create_item($canvas, 1, 4, 'square', 'red', 'Patricia');</PRE>
- <PRE>
- # Single-clicking with left on a 'circle' item invokes a procedure
- $canvas->bind('circle', '<1>' => sub {handle_circle($canvas)});
- # Double-clicking with left on a 'blue' item invokes a procedure
- $canvas->bind('blue', '<Double-1>' => sub {handle_blue($canvas)});
- MainLoop;</PRE>
- <PRE>
- # Create an item; use parameters as tags (this is not a default!)
- sub create_item {
- my ($can, $x, $y, $form, $color, $name) = @_;</PRE>
- <PRE>
- 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);
- }</PRE>
- <PRE>
- # 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 'circle');
- $name = $_;
- last;
- }
- return $name;
- }</PRE>
- <PRE>
- sub handle_circle {
- my ($can) = @_;
- my $name = get_name($can);
- print "Action on circle $name...\n";
- }</PRE>
- <PRE>
- sub handle_blue {
- my ($can) = @_;
- my $name = get_name($can);
- print "Action on blue item $name...\n";
- }</PRE>
- <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%>
- <TR><TD CLASS=block VALIGN=MIDDLE WIDTH=100% BGCOLOR="#cccccc">
- <STRONG><P CLASS=block> perl/Tk - Writing Tk applications in perl5.</P></STRONG>
- </TD></TR>
- </TABLE>
-
- </BODY>
-
- </HTML>
-