Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | =head1 NAME |
2 | ||
3 | perl/Tk - Writing Tk applications in perl5. | |
4 | ||
5 | =for category Introduction | |
6 | ||
7 | =head1 DESCRIPTION | |
8 | ||
9 | This manual page is for beginners. It assumes you know some perl, | |
10 | and have got perl+Tk running. | |
11 | Please run the 'widget' demo before reading this text; it will teach you | |
12 | the various widget types supported by Tk. | |
13 | ||
14 | =head1 Some background | |
15 | ||
16 | Tk GUI programming is event-driven. (This may already be familiar to you.) | |
17 | In event-driven programs, the main GUI loop is outside of the user program | |
18 | and inside the GUI library. This loop will watch all events of interest, | |
19 | and activate the correct handler procedures to handle these events. | |
20 | Some of these handler procedures may be user-supplied; others will be part | |
21 | of the library. | |
22 | ||
23 | For a programmer, this means that you're not watching what is happening; | |
24 | instead, you are requested by the toolkit to perform actions whenever | |
25 | necessary. | |
26 | So, you're not watching for 'raise window / close window / redraw window' | |
27 | requests, but you tell the toolkit which routine will handle such cases, | |
28 | and the toolkit will call the procedures when required. | |
29 | ||
30 | =head1 First requirements | |
31 | ||
32 | Any perl program that uses Tk needs to include C<use Tk>. | |
33 | A program should also use C<use strict> and the B<-w> switch to ensure | |
34 | the program is working without common errors. | |
35 | ||
36 | Any Tk application starts by creating the Tk main window. You then create | |
37 | items inside the main window, or create new windows, before starting the | |
38 | mainloop. | |
39 | (You can also create more items and windows while you're running.) | |
40 | The items will be shown on the display after you C<pack> them; | |
41 | more info on this later. | |
42 | Then you do a Tk mainloop; this will start the GUI and handle all events. | |
43 | That's your application. | |
44 | A trivial one-window example is show below: | |
45 | ||
46 | #! /usr/bin/perl5 -w | |
47 | ||
48 | use strict; | |
49 | use Tk; | |
50 | ||
51 | my $main = MainWindow->new; | |
52 | $main->Label(-text => 'Hello, world!')->pack; | |
53 | $main->Button(-text => 'Quit', | |
54 | -command => [$main => 'destroy'] | |
55 | )->pack; | |
56 | MainLoop; | |
57 | ||
58 | Please run this example. It shows you two items types also shown in the | |
59 | widget demo; it also shows you how items are created and packed. | |
60 | Finally, note the typical Tk style using C<-option> =E<gt> C<value> pairs. | |
61 | ||
62 | =head1 Item creation | |
63 | ||
64 | Tk windows and widgets are hierarchical, S<i.e. one> includes one or more | |
65 | others. You create the first Tk window using C<MainWindow-E<gt>new>. | |
66 | This returns a window handle, assigned to C<$main> in the example above. | |
67 | Keep track of the main handle. | |
68 | ||
69 | You can use any Tk handle to create sub-items within the window or widget. | |
70 | This is done by calling the Tk constructor method on the variable. | |
71 | In the example above, the C<Label> method called from C<$main> creates a | |
72 | label widget inside the main window. In the constructor call, you can specify | |
73 | various options; you can later add or change options for any widget | |
74 | using the C<configure> method, which takes the same parameters as the | |
75 | constructor. | |
76 | The one exception to the hierarchical structure is the C<Toplevel> constructor, | |
77 | which creates a new outermost window. | |
78 | ||
79 | After you create any widget, you must render it by calling C<pack>. (This | |
80 | is not entirely true; more info later). If you do not need to refer to | |
81 | the widget after construction and packing, call C<pack> off the constructor | |
82 | results, as shown for the label and button in the example above. | |
83 | Note that the result of the compound call is the result of C<pack>, | |
84 | which is a valid Tk handle. | |
85 | ||
86 | Windows and widgets are deleted by calling C<destroy> on them; | |
87 | this will delete and un-draw the widget and all its children. | |
88 | ||
89 | =head1 Standard Tk types | |
90 | ||
91 | =over 4 | |
92 | ||
93 | =item Button | |
94 | ||
95 | =item Radiobutton | |
96 | ||
97 | =item Checkbutton | |
98 | ||
99 | =item Listbox | |
100 | ||
101 | =item Scrollbar | |
102 | ||
103 | =item Entry | |
104 | ||
105 | =item Text | |
106 | ||
107 | =item Canvas | |
108 | ||
109 | =item Frame | |
110 | ||
111 | =item Toplevel | |
112 | ||
113 | =item Scale | |
114 | ||
115 | =item Menu | |
116 | ||
117 | =item Menubutton | |
118 | ||
119 | =back | |
120 | ||
121 | =head1 Variables and callback routines | |
122 | ||
123 | Most graphical interfaces are used to set up a set of values and conditions, | |
124 | and then perform the appropriate action. The Tk toolkit is different | |
125 | from your average text-based prompting or menu driven system in that you do | |
126 | not collect settings yourself, and decide on an action based on an | |
127 | input code; instead, you leave these | |
128 | values to your toolkit and only get them when the action is performed. | |
129 | ||
130 | So, where a traditional text-based system would look like this: | |
131 | (yes, this is obviously dumb code) | |
132 | ||
133 | #! /usr/bin/perl5 -w | |
134 | ||
135 | use strict; | |
136 | ||
137 | print "Please type a font name\n"; | |
138 | my $font = <>; chomp $font; | |
139 | # Validate font | |
140 | ||
141 | print "Please type a file name\n"; | |
142 | my $filename = <>; chomp $filename; | |
143 | # Validate filename | |
144 | ||
145 | print "Type <1> to fax, <2> to print\n"; | |
146 | my $option = <>; chomp $option; | |
147 | if ($option eq 1) { | |
148 | print "Faxing $filename in font $font\n"; | |
149 | } elsif ($option eq 2) { | |
150 | print "Now sending $filename to printer in font $font\n"; | |
151 | } | |
152 | ||
153 | The (slightly larger) example below shows how to do this is Tk. | |
154 | Note the use of callbacks. Note, also, that Tk handles the values, and | |
155 | the subroutine uses C<get> to get at the values. | |
156 | If a user changes his mind and wants to change the font again, | |
157 | the application never notices; it's all handled by Tk. | |
158 | ||
159 | #! /usr/bin/perl5 -w | |
160 | ||
161 | use strict; | |
162 | use Tk; | |
163 | ||
164 | my $main = MainWindow->new; | |
165 | $main->Label(-text => 'Print file')->pack; | |
166 | my $font = $main->Entry(-width => 10); | |
167 | $font->pack; | |
168 | my $filename = $main->Entry(-width => 10); | |
169 | $filename->pack; | |
170 | $main->Button(-text => 'Fax', | |
171 | -command => sub{do_fax($filename, $font)} | |
172 | )->pack; | |
173 | $main->Button(-text => 'Print', | |
174 | -command => sub{do_print($filename, $font)} | |
175 | )->pack; | |
176 | MainLoop; | |
177 | ||
178 | sub do_fax { | |
179 | my ($file, $font) = @_; | |
180 | my $file_val = $file->get; | |
181 | my $font_val = $font->get; | |
182 | print "Now faxing $file_val in $font_val\n"; | |
183 | } | |
184 | ||
185 | sub do_print { | |
186 | my ($file, $font) = @_; | |
187 | my $file_val = $file->get; | |
188 | my $font_val = $font->get; | |
189 | print "Sending file $file_val to printer in $font_val\n"; | |
190 | } | |
191 | ||
192 | =head1 The packer. Grouping and frames. | |
193 | ||
194 | In the examples above, you must have noticed the L<pack|Tk::pack> calls. | |
195 | This is one of the more complicated parts of Tk. The basic idea | |
196 | is that any window or widget should be subject to a Tk widget placement manager; | |
197 | the I<packer> is one of the placement managers. | |
198 | ||
199 | The actions of the packer are rather simple: when applied | |
200 | to a widget, the packer positions that widget on the indicated position | |
201 | within the remaining space in its parent. By default, the position is | |
202 | on top; this means the next items will be put below. You can also | |
203 | specify the left, right, or bottom positions. Specify position | |
204 | using B<-side =E<gt> 'right'>. | |
205 | ||
206 | Additional packing parameters specify the behavior of the widget when | |
207 | there is some space left in the frame or when the window size is | |
208 | increased. If widgets should maintain a fixed size, specify nothing; | |
209 | this is the default. For widgets that you want to fill up the current | |
210 | horizontal space, specify B<-fill =E<gt> 'x'>, B<y>, or B<both>; for | |
211 | widgets that should grow, specify B<-expand =E<gt> 1>. These | |
212 | parameters are not shown in the example below; see the widget demo. | |
213 | ||
214 | If you want to group some items within a window that have a different | |
215 | packing order than others, you can include them in a Frame. This is a | |
216 | do-nothing window type that is meant for packing (and to play games | |
217 | with borders and colors). | |
218 | ||
219 | The example below shows the use of pack and frames: | |
220 | ||
221 | #! /usr/bin/perl5 -w | |
222 | ||
223 | use strict; | |
224 | use Tk; | |
225 | ||
226 | # Take top, the bottom -> now implicit top is in the middle | |
227 | my $main = MainWindow->new; | |
228 | $main->Label(-text => 'At the top (default)')->pack; | |
229 | $main->Label(-text => 'At the bottom')->pack(-side => 'bottom'); | |
230 | $main->Label(-text => 'The middle remains')->pack; | |
231 | ||
232 | # Since left and right are taken, bottom will not work... | |
233 | my $top1 = $main->Toplevel; | |
234 | $top1->Label(-text => 'Left')->pack(-side => 'left'); | |
235 | $top1->Label(-text => 'Right')->pack(-side => 'right'); | |
236 | $top1->Label(-text => '?Bottom?')->pack(-side => 'bottom'); | |
237 | ||
238 | # But when you use frames, things work quite alright | |
239 | my $top2 = $main->Toplevel; | |
240 | my $frame = $top2->Frame; | |
241 | $frame->pack; | |
242 | $frame->Label(-text => 'Left2')->pack(-side => 'left'); | |
243 | $frame->Label(-text => 'Right2')->pack(-side => 'right'); | |
244 | $top2->Label(-text => 'Bottom2')->pack(-side => 'bottom'); | |
245 | ||
246 | MainLoop; | |
247 | ||
248 | =head1 More than one window | |
249 | ||
250 | Most real applications require more than one window. As you read before, | |
251 | you can create more outermost windows by using Toplevel. Each window | |
252 | is independent; destroying a toplevel window does not affect the others as | |
253 | long as they are not a child of the closed toplevel. | |
254 | Exiting the main window will end the application. | |
255 | The example below shows a trivial three-window application: | |
256 | ||
257 | #! /usr/bin/perl5 -w | |
258 | ||
259 | use strict; | |
260 | use Tk; | |
261 | ||
262 | my $main = MainWindow->new; | |
263 | fill_window($main, 'Main'); | |
264 | my $top1 = $main->Toplevel; | |
265 | fill_window($top1, 'First top-level'); | |
266 | my $top2 = $main->Toplevel; | |
267 | fill_window($top2, 'Second top-level'); | |
268 | MainLoop; | |
269 | ||
270 | sub fill_window { | |
271 | my ($window, $header) = @_; | |
272 | $window->Label(-text => $header)->pack; | |
273 | $window->Button(-text => 'close', | |
274 | -command => [$window => 'destroy'] | |
275 | )->pack(-side => 'left'); | |
276 | $window->Button(-text => 'exit', | |
277 | -command => [$main => 'destroy'] | |
278 | )->pack(-side => 'right'); | |
279 | } | |
280 | ||
281 | =head1 More callbacks | |
282 | ||
283 | So far, all callback routines shown called a user procedure. | |
284 | You can also have a callback routine call another Tk routine. | |
285 | This is the way that scroll bars are implemented: scroll-bars | |
286 | can call a Tk item or a user procedure, whenever their position | |
287 | has changed. The Tk item that has a scrollbar attached calls the | |
288 | scrollbar when its size or offset has changed. In this way, | |
289 | the items are linked. You can still ask a scrollbar's position, | |
290 | or set it by hand - but the defaults will be taken care of. | |
291 | ||
292 | The example below shows a listbox with a scroll bar. Moving | |
293 | the scrollbar moves the listbox. Scanning a listbox (dragging | |
294 | an item with the left mouse button) moves the scrollbar. | |
295 | ||
296 | #! /usr/bin/perl5 -w | |
297 | ||
298 | use strict; | |
299 | use Tk; | |
300 | ||
301 | my $main = MainWindow->new; | |
302 | my $box = $main->Listbox(-relief => 'sunken', | |
303 | -width => -1, # Shrink to fit | |
304 | -height => 5, | |
305 | -setgrid => 1); | |
306 | my @items = qw(One Two Three Four Five Six Seven | |
307 | Eight Nine Ten Eleven Twelve); | |
308 | foreach (@items) { | |
309 | $box->insert('end', $_); | |
310 | } | |
311 | my $scroll = $main->Scrollbar(-command => ['yview', $box]); | |
312 | $box->configure(-yscrollcommand => ['set', $scroll]); | |
313 | $box->pack(-side => 'left', -fill => 'both', -expand => 1); | |
314 | $scroll->pack(-side => 'right', -fill => 'y'); | |
315 | ||
316 | MainLoop; | |
317 | ||
318 | =head1 Canvases and tags | |
319 | ||
320 | One of the most powerful window types in Tk is the Canvas window. | |
321 | In a canvas window, you can draw simple graphics and include | |
322 | other widgets. The canvas area may be larger than the visible window, | |
323 | and may then be scrolled. Any item you draw on the canvas has its own id, | |
324 | and may optionally have one or more I<tags>. You may refer to any | |
325 | item by its id, and may refer to any group of items by a common tag; | |
326 | you can move, delete, or change groups of items using these tags, | |
327 | and you can I<bind> actions to tags. For a properly designed (often | |
328 | structured) canvas, you can specify powerful actions quite simply. | |
329 | ||
330 | In the example below, actions are bound to circles (single click) | |
331 | and blue items (double-click); obviously, this can be extended to any | |
332 | tag or group of tags. | |
333 | ||
334 | #! /usr/bin/perl5 -w | |
335 | ||
336 | use strict; | |
337 | use Tk; | |
338 | ||
339 | # Create main window and canvas | |
340 | my $main = MainWindow->new; | |
341 | my $canvas = $main->Canvas; | |
342 | $canvas->pack(-expand => 1, -fill => 'both'); | |
343 | ||
344 | # Create various items | |
345 | create_item($canvas, 1, 1, 'circle', 'blue', 'Jane'); | |
346 | create_item($canvas, 4, 4, 'circle', 'red', 'Peter'); | |
347 | create_item($canvas, 4, 1, 'square', 'blue', 'James'); | |
348 | create_item($canvas, 1, 4, 'square', 'red', 'Patricia'); | |
349 | ||
350 | # Single-clicking with left on a 'circle' item invokes a procedure | |
351 | $canvas->bind('circle', '<1>' => sub {handle_circle($canvas)}); | |
352 | # Double-clicking with left on a 'blue' item invokes a procedure | |
353 | $canvas->bind('blue', '<Double-1>' => sub {handle_blue($canvas)}); | |
354 | MainLoop; | |
355 | ||
356 | # Create an item; use parameters as tags (this is not a default!) | |
357 | sub create_item { | |
358 | my ($can, $x, $y, $form, $color, $name) = @_; | |
359 | ||
360 | my $x2 = $x + 1; | |
361 | my $y2 = $y + 1; | |
362 | my $kind; | |
363 | $kind = 'oval' if ($form eq 'circle'); | |
364 | $kind = 'rectangle' if ($form eq 'square'); | |
365 | $can->create(($kind, "$x" . 'c', "$y" . 'c', | |
366 | "$x2" . 'c', "$y2" . 'c'), | |
367 | -tags => [$form, $color, $name], | |
368 | -fill => $color); | |
369 | } | |
370 | ||
371 | # This gets the real name (not current, blue/red, square/circle) | |
372 | # Note: you'll want to return a list in realistic situations... | |
373 | sub get_name { | |
374 | my ($can) = @_; | |
375 | my $item = $can->find('withtag', 'current'); | |
376 | my @taglist = $can->gettags($item); | |
377 | my $name; | |
378 | foreach (@taglist) { | |
379 | next if ($_ eq 'current'); | |
380 | next if ($_ eq 'red' or $_ eq 'blue'); | |
381 | next if ($_ eq 'square' or $_ eq 'circle'); | |
382 | $name = $_; | |
383 | last; | |
384 | } | |
385 | return $name; | |
386 | } | |
387 | ||
388 | sub handle_circle { | |
389 | my ($can) = @_; | |
390 | my $name = get_name($can); | |
391 | print "Action on circle $name...\n"; | |
392 | } | |
393 | ||
394 | sub handle_blue { | |
395 | my ($can) = @_; | |
396 | my $name = get_name($can); | |
397 | print "Action on blue item $name...\n"; | |
398 | } | |
399 |