Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
UserGuide(3)	      User Contributed Perl Documentation	  UserGuide(3)

NAME
       Tk::UserGuide - Writing Tk applications in Perl 5

DESCRIPTION
       This document is	for beginners.	It assumes you know some Perl, and
       have it and Tk running.	If you are not currently reading this document
       courtesy	of the widget demonstration program, please be sure to run
       widget, as it will show you the various widget types supported by Tk
       and how to use them. widget should be installed in your default path,
       so type widget at a command prompt.

       Here are	links to other novice tutorials:

       <http://www.lehigh.edu/~sol0/ptk/tpj1.html>
       <http://www.lehigh.edu/~sol0/ptk/perlmonth01/pm1.html>

       Mastering Perl/Tk is the	definitive book	on Perl/Tk:

       <http://www.oreilly.com/catalog/mastperltk>

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 - initiated by
       calling MainLoop	- watches all events of	interest and activates the
       correct handler procedures to handle these events.  Some	of these
       handler procedures may be user-supplied;	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 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. These procedures are known as callbacks, and
       some of them you	write yourself.

First Requirements
       Perl programs that use Tk need 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 Perl/Tk application starts by creating the Tk MainWindow.  You then
       create items inside the MainWindow, and/or create new windows called
       Toplevels that also contain child items,	before starting	the MainLoop,
       which is	the last logical statment in your program. You can also	create
       more items and windows while you're running, using callbacks.  Items
       are only	shown on the display after they	have been arranged by a
       geometry	manager	like pack; more	information on this later.  MainLoop
       starts the GUI and handle all events.  That's all there is to it!  A
       trivial one-window example is shown below:

	   #!/usr/bin/perl -w
	   use Tk;
	   use strict;

	   my $mw = MainWindow->new;
	   $mw->Label(-text => 'Hello, world!')->pack;
	   $mw->Button(
	       -text	=> 'Quit',
	       -command	=> sub { exit },
	   )->pack;
	   MainLoop;

       Please run this example.	 It shows you two widget types,	a Label	and a
       Button, and how they are	packed.	When clicked, the Button widget
       invokes the callback specified by the "-command"	option.	 Finally, note
       the typical Tk style using "-option" => "value" pairs.

Widget creation
       Tk windows and widgets are hierarchical,	i.e.A one window includes one
       or more other windows.  You create the first Tk window using
       "MainWindow->new".  This	returns	a window handle, assigned to $mw in
       the example above.  Keep	track of the main handle, commonly called a
       widget reference.

       You can use any Tk handle to create child widgets within	the window (or
       widget).	 This is done by calling the Tk	constructor method on the
       variable.  In the example above,	the "Label" method called from $mw
       creates a Label widget inside the MainWindow.  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 (other than the MainWindow or Toplevels,
       you must	render it by calling pack.  (This is not entirely true;	more
       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 widgets
       Here is an itemize of the standard Tk widget set.

       Button
       Canvas
       Checkbutton
       Entry
       Frame
       Label
       Labelframe
       Listbox
       Menu
       Menubutton
       Message
       Panedwindow
       Radiobutton
       Scale
       Scrollbar
       Spinbox
       Text
       Toplevel

       Perl/Tk provides	an equal number	of new widgets,	above and beyond this
       core set.

       Adjuster
       Balloon
       BrowseEntry
       ColorEditor
       Dialog
       DialogBox
       DirTree
       ErrorDialog
       FBox
       FileSelect
       HList
       LabEntry
       LabFrame
       NoteBook
       Optionmenu
       Pane
       ProgressBar
       ROText
       Table
       TextUndo
       Tiler
       TList
       Tree

Variables and callback routines
       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.

       So, where a traditional text-based system would look like this:

	   #!/usr/bin/perl -w
	   use strict;

	   print "Please type a	font name\n";
	   my $font = <>; chomp	$font;
	   # Validate font

	   print "Please type a	file name\n";
	   my $filename	= <>; chomp $filename;
	   # Validate filename

	   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";
	   }

       The slightly larger example below shows how to do this in Tk.  Note the
       use of callbacks.  Note,	also, that Tk handles the values, and the
       subroutine uses the method 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/perl -w
	   use Tk;
	   use strict;

	   my $mw = MainWindow->new;

	   $mw->Label(-text => 'File Name')->pack;
	   my $filename	= $mw->Entry(-width => 20);
	   $filename->pack;

	   $mw->Label(-text => 'Font Name')->pack;
	   my $font = $mw->Entry(-width	=> 10);
	   $font->pack;

	   $mw->Button(
	       -text =>	'Fax',
	       -command	=> sub{do_fax($filename, $font)}
	   )->pack;

	   $mw->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 $font_val\n";
	   }

	   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	$font_val\n";
	   }

The packer - grouping with Frame widgets
       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 subject to a Tk geometry manager; the	packer
       is one of the placement managers, and grid is another.

       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 -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 and/or vertical 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 demonstration.

       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	or filling (and	to
       play games with borders and colors).

       The example below shows the use of pack and Frames:

	   #!/usr/bin/perl -w
	   use Tk;
	   use strict;

	   # Take top and the bottom - now implicit top	is in the middle
	   my $mw = MainWindow->new;
	   $mw->title( 'The MainWindow'	);
	   $mw->Label(-text => 'At the top (default)')->pack;
	   $mw->Label(-text => 'At the bottom')->pack(-side => 'bottom');
	   $mw->Label(-text => 'The middle remains')->pack;

	   # Since left	and right are taken, bottom will not work...
	   my $top1 = $mw->Toplevel;
	   $top1->title( 'Toplevel 1' );
	   $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	alright
	   my $top2 = $mw->Toplevel;
	   $top2->title( 'Toplevel 2' );
	   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 just saw,
       you can create more outermost windows by	using a	Toplevel widget.  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.
       However,	exiting	the MainWindow will destroy all	remaining Toplevel
       widgets and end the application.	 The example below shows a trivial
       three-window application:

	   #!/usr/bin/perl -w
	   use Tk;
	   use strict;

	   my $mw = MainWindow->new;
	   fill_window($mw, 'Main');
	   my $top1 = $mw->Toplevel;
	   fill_window($top1, 'First top-level');
	   my $top2 = $mw->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	=> 'destroy']
	       )->pack(-side =>	'left');
	       $window->Button(
		   -text    => 'exit',
		   -command => [$mw => 'destroy']
	       )->pack(-side =>	'right');
	   }

More callbacks
       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.

       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.

	    #!/usr/bin/perl -w
	    use	Tk;
	    use	strict;

	    my $mw = MainWindow->new;
	    my $box = $mw->Listbox(
		-relief	=> 'sunken',
		-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 =	$mw->Scrollbar(-command	=> ['yview', $box]);
	   $box->configure(-yscrollcommand => ['set', $scroll]);
	   $box->pack(-side => 'left', -fill =>	'both',	-expand	=> 1);
	   $scroll->pack(-side => 'right', -fill => 'y');

	   MainLoop;

       Note that there's a convenience method Scrolled which helps
       constructing widgets with automatically managed scrollbars.

Canvases and tags
       One of the most powerful	widgets	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/perl -w
	   use Tk;
	   use strict;

	   # Create B<MainWindow> and canvas
	   my $mw = MainWindow->new;
	   my $canvas =	$mw->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', 'Peter');
	   create_item($canvas,	4, 1, 'square',	'blue',	'James');
	   create_item($canvas,	1, 4, 'square',	'red', 'Patricia');

	   # 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;

	   # 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 'circle');
		   $name = $_;
		   last;
	       }
	       return $name;
	   }

	   sub handle_circle {
	       my ($can) = @_;
	       my $name	= get_name($can);
	       print "Action on	circle $name...\n";
	   }

	   sub handle_blue {
	       my ($can) = @_;
	       my $name	= get_name($can);
	       print "Action on	blue item $name...\n";
	   }

Perl/Tk	and Unicode
       Perl/Tk follows Perl's model of handling	Unicode. That is, if a string
       is correctly flagged as a "character" string in the sense like
       described in "TERMINOLOGY" in Encode, then Perl/Tk will very probably
       display and handle this string correctly.

       Note that every variable	which is passed	somehow	into a Perl/Tk method
       will be implicitely changed into	an internally utf8-flagged variable.
       Semantically nothing changes, as	the series of codepoints stays the
       same, but things	will change when variables with	high-bit iso-8859-1
       characters will be passed to the	"outer"	world. In this case you	have
       to explicitely mark the encoding	of your	output stream if using IO, or
       encode the variables using Encode for other style of communication.

       This is the theory, now some examples.

       If you use non-iso-8859-1 characters in the source code,	then use
       either the "use utf8;" or "use encoding 'encodingname'" pragma:

	    use	utf8;
	    use	Tk;
	    my $x = "some characters using utf8	encoding";
	    tkinit->Label(-text	=> $x)->pack;
	    MainLoop;

       For data	that comes from	a file you have	to specify the encoding	unless
       it's encoded as ascii or	iso-8559-1:

	    use	Tk;
	    open my $FH, "<:encoding(utf-8)", "filename" or die	$!;
	    # or for utf-16 data: open my $FH, "<:encoding(utf-16)", "filename"	or die $!;
	    my $data = <$FH>;
	    tkinit->Label(-text	=> $data)->pack;
	    MainLoop;

       Likewise, the encoding must be specified	for all	data which is read
       from Tk widgets and that	shall be output	into a file. For the output,
       the encoding should be always specified,	even if	it is iso-8859-1:

	    use	Tk;
	    $mw	= tkinit;
	    $mw->Entry(-textvariable =>	\$input)->pack;
	    $mw->Button(
		-text => "Write	to file",
		-command => sub	{
		    open my $FH, ">:encoding(iso-8859-1)", "filename" or die $!;
		    print $FH $input;
		},
	    )->pack;
	    MainLoop;

       Note that Tk is Unicode-capable.	So you need to be prepared that	the
       user has	the appropriate	input methods activated	to enter non-ascii
       characters. If an output	encoding is used which does not	cover the
       whole of	Unicode	codepoints then	a warning will be issued when writing
       the file, like this:

	   "\x{20ac}" does not map to iso-8859-1 at /usr/local/lib/perl5/site_perl/5.8.8/mach/Tk.pm line 250.

       Also, the same hexadecimal notation will	be used	as replacements	for
       the unhandled characters.

       Handling	encoding in I/O	is pretty simple using the "encoding" PerlIO
       layer, as described above. In other cases, such as when dealing with
       databases, encoding the data usually has	to be done manually, unless
       the database driver has some means for automatically do this for	you.
       So when working with a MySQL database, one could	use:

	    use	Tk;
	    use	DBI;
	    use	Encode qw(encode);
	    $mw	= tkinit;
	    $mw->Entry(-textvariable =>	\$input)->pack;
	    $mw->Button(
		-text => "Write	to database",
		-command => sub	{
		    my $dbh = DBI->connect("dbi:mysql:test", "root", "") or die;
		    my $encoded_input =	encode("iso-8859-1", $input);
		    $dbh->do("INSERT INTO testtable VALUES (?)", undef,	$encoded_input)	or die;
		},
	    )->pack;
	    MainLoop;

       Unfortunately, there are	still places in	Perl ignorant of Unicode. One
       of these	places are filenames. Consequently, the	file selectors in
       Perl/Tk do not handle encoding of filenames properly. Currently they
       suppose that filenames are in iso-8859-1	encoding, at least on Unix
       systems.	As soon	as Perl	has a concept of filename encodings, then
       Perl/Tk will also implement such	schemes.

perl v5.32.1			  2013-11-15			  UserGuide(3)

NAME | DESCRIPTION | Some Background | First Requirements | Widget creation | Standard Tk widgets | Variables and callback routines | The packer - grouping with Frame widgets | More than one window | More callbacks | Canvases and tags | Perl/Tk and Unicode

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Tk::UserGuide&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help