diff options
Diffstat (limited to 'Master/tlpkg/tlperl.straw/lib/Tk/UserGuide.pod')
-rwxr-xr-x | Master/tlpkg/tlperl.straw/lib/Tk/UserGuide.pod | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl.straw/lib/Tk/UserGuide.pod b/Master/tlpkg/tlperl.straw/lib/Tk/UserGuide.pod new file mode 100755 index 00000000000..4d1d4ffaa5c --- /dev/null +++ b/Master/tlpkg/tlperl.straw/lib/Tk/UserGuide.pod @@ -0,0 +1,493 @@ +=head1 NAME + +Perl/Tk - Writing Tk applications in Perl 5 + +=for category Introduction + +=head1 DESCRIPTION + +This document is for beginners. It assumes you know some B<Perl>, and +have it and Tk running. If you are I<not> currently reading this +document courtesy of the B<widget> demonstration program, please be +sure to run B<widget>, as it will show you the various widget types +supported by Tk and how to use them. B<widget> should be installed in +your default path, so type I<widget> at a command prompt. + +Here are links to other novice tutorials: + +L<http://www.lehigh.edu/~sol0/ptk/tpj1.html> +L<http://www.lehigh.edu/~sol0/ptk/perlmonth01/pm1.html> + +I<Mastering Perl/Tk> is the definitive book on Perl/Tk: + +L<http://www.oreilly.com/catalog/mastperltk> + +=head1 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 B<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 I<callbacks>, and some of them you write yourself. + +=head1 First Requirements + +B<Perl> programs that use Tk need to include C<use Tk>. +A program should also use C<use strict> and the B<-w> switch to ensure +the program is working without common errors. + +Any Perl/Tk application starts by creating the Tk B<L<MainWindow|Tk::MainWindow>>. You +then create items inside the B<MainWindow>, and/or create new windows +called B<L<Toplevel|Tk::Toplevel>>s that also contain child items, before starting the +B<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 I<geometry manager> like B<L<pack|Tk::pack>>; more information on +this later. B<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 B<L<Label|Tk::Label>> +and a B<L<Button|Tk::Button>>, and how they are packed. When clicked, the B<Button> +widget invokes the callback specified by the C<-command> option. Finally, +note the typical Tk style using C<-option> =E<gt> C<value> pairs. + +=head1 Widget creation + +Tk windows and widgets are hierarchical, S<i.e. one> window includes +one or more other windows. You create the first Tk window using +C<MainWindow-E<gt>new>. This returns a window handle, assigned to +C<$mw> in the example above. Keep track of the main handle, commonly +called a I<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 C<Label> method called from +C<$mw> creates a B<Label> widget inside the B<MainWindow>. In the +constructor call, you can specify various options; you can later add +or change options for any widget using the B<configure> method, which +takes the same parameters as the constructor. The one exception to +the hierarchical structure is the B<Toplevel> constructor, which +creates a new outermost window. + +After you create any widget (other than the B<MainWindow> or +B<Toplevel>s, you must render it by calling B<pack>. (This is not +entirely true; more later)). If you do not need to refer to the widget +after construction and packing, call B<pack> off the constructor +results, as shown for the B<Label> and B<Button> in the example above. Note +that the result of the compound call is the result of B<pack>, which +is a valid Tk handle. + +Windows and widgets are deleted by calling B<destroy> on them; +this will delete and un-draw the widget and all its children. + +=head1 Standard Tk widgets + +Here is an itemize of the standard Tk widget set. + +=over 4 + +=item L<Button|Tk::Button> + +=item L<Canvas|Tk::Canvas> + +=item L<Checkbutton|Tk::Checkbutton> + +=item L<Entry|Tk::Entry> + +=item L<Frame|Tk::Frame> + +=item L<Label|Tk::Label> + +=item L<Labelframe|Tk::Labelframe> + +=item L<Listbox|Tk::Listbox> + +=item L<Menu|Tk::Menu> + +=item L<Menubutton|Tk::Menubutton> + +=item L<Message|Tk::Message> + +=item L<Panedwindow|Tk::Panedwindow> + +=item L<Radiobutton|Tk::Radiobutton> + +=item L<Scale|Tk::Scale> + +=item L<Scrollbar|Tk::Scrollbar> + +=item L<Spinbox|Tk::Spinbox> + +=item L<Text|Tk::Text> + +=item L<Toplevel|Tk::Toplevel> + +=back + +Perl/Tk provides an equal number of new widgets, above and beyond this +core set. + +=over 4 + +=item L<Adjuster|Tk::Adjuster> + +=item L<Balloon|Tk::Balloon> + +=item L<BrowseEntry|Tk::BrowseEntry> + +=item L<ColorEditor|Tk::ColorEditor> + +=item L<Dialog|Tk::Dialog> + +=item L<DialogBox|Tk::DialogBox> + +=item L<DirTree|Tk::DirTree> + +=item ErrorDialog + +=item L<FBox|Tk::FBox> + +=item L<FileSelect|Tk::FileSelect> + +=item L<HList|Tk::HList> + +=item LabEntry + +=item L<LabFrame|Tk::LabFrame> + +=item L<NoteBook|Tk::NoteBook> + +=item L<Optionmenu|Tk::Optionmenu> + +=item L<Pane|Tk::Pane> + +=item L<ProgressBar|Tk::ProgressBar> + +=item L<ROText|Tk::ROText> + +=item L<Table|Tk::Table> + +=item L<TextUndo|Tk::TextUndo> + +=item L<Tiler|Tk::Tiler> + +=item L<TList|Tk::TList> + +=item L<Tree|Tk::Tree> + +=back + +=head1 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 B<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"; + } + +=head1 The packer - grouping with Frame widgets + +In the examples above, you must have noticed the B<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 +I<packer> is one of the placement managers, and B<L<grid|Tk::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 B<-side =E<gt> 'right'>. + +Additional packing parameters specify the behavior of the widget when +there is some space left in the B<L<Frame|Tk::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 B<-fill =E<gt> 'x'>, B<'y'>, +or B<'both'>; for widgets that should grow, specify B<-expand =E<gt> 1>. +These parameters are not shown in the example below; see the B<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; + +=head1 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 B<Toplevel> widget. +Each window is independent; destroying a B<Toplevel> window does not +affect the others as long as they are not a child of the closed +B<Toplevel>. However, exiting the B<MainWindow> will destroy all remaining +B<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'); + } + +=head1 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 B<L<Listbox|Tk::Listbox>> with a scroll bar. Moving +the scrollbar moves the B<Listbox>. Scanning a B<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 B<L<Scrolled|Tk::Scrolled>> +which helps constructing widgets with automatically managed +scrollbars. + +=head1 Canvases and tags + +One of the most powerful widgets in Tk is the B<L<Canvas|Tk::Canvas>> window. +In a B<Canvas> window, you can draw simple graphics and include +other widgets. The B<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 I<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 I<bind> actions to tags. For a properly designed (often +structured) B<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"; + } |