Responding to Tk Resize Events (Perl Cookbook, 2nd Edition)

## 15.16. Responding to Tk Resize Events

### 15.16.1. Problem

You've written a Tk program, but your widget layout goes awry when the user resizes their window.

### 15.16.2. Solution

You can prevent the user from resizing the window by intercepting the Configure event:

>     use Tk;

>     $main = MainWindow->new( );

>     $main->bind('<Configure>' => sub {
>         $xe = $main->XEvent;
>         $main->maxsize($xe->w, $xe->h);
>         $main->minsize($xe->w, $xe->h);
>     });

Or you can use `pack` to control how each widget resizes and expands when the user resizes its container:

>     $widget->pack( -fill => "both", -expand => 1 );
>     $widget->pack( -fill => "x",    -expand => 1 );

### 15.16.3. Discussion

By default, packed widgets resize if their container changes size—they don't scale themselves or their contents to the new size. This can lead to empty space between widgets, or cropped or cramped widgets if the user resizes the window.

One solution is to prevent resizing. We `bind` to the `Configure` event, which is sent when a widget's size or position changes, registering a callback to reset the window's size. This is how you'd ensure a pop-up error-message box couldn't be resized.

You often want to let the user resize the application's windows. You must then define how each widget will react. Do this through the arguments to the `pack` method: `-fill` controls the dimensions the widget will resize in, and `-expand` controls whether the widget's size will change to match available space. The `-expand` option takes a Boolean value, true or false. The `-fill` option takes a string indicating the dimensions the widget can claim space in: "`x`", "`y`", "`both`", or "`none`".

The solution requires both options. Without `-fill`, `-expand` won't claim space to grow into. Without `-expand`, `-fill` will claim empty space but won't expand in it.

Different parts of your application will behave differently. The main area of a web browser, for example, should probably change size in both dimensions when the window is resized. You'd pack the widget like this:

>     $mainarea->pack( -fill => "both", -expand => 1 );

The menubar above the main area, though, should expand horizontally but not vertically. You'd pack the widget thus:

>     $menubar->pack( -fill => "x", -expand => 1 );

Associated with resizing is the need to anchor a widget to part of its container. Here's how you'd anchor the menubar to the top-left corner of its container when you call `pack`:

>     $menubar->pack (-fill     => "x",
>                     -expand   => 1,
>                     -anchor   => "nw" );

Now when you resize it, the menubar stays at the top of the window where it belongs, instead of being centered in wide open space.

### 15.16.4. See Also

The pack(n), XEvent(3), and XConfigureEvent(3) manpages (if you have them); Tcl and the Tk Toolkit, by John Ousterhout (Addison-Wesley); Mastering Perl/Tk

Copyright © 2003 O'Reilly & Associates. All rights reserved.