Learning PERL/Tk: Graphical User Interfaces with Perl

Overview

Learning Perl/Tk is a tutorial for Perl/Tk, the extension to Perl for creating graphical user interfaces. With Tk, Perl programs can be window-based rather than command-line based, with buttons, entry fields, listboxes, menus, and scrollbars. Originally developed for the Tcl language, the Perl port of the Tk toolkit liberates Perl programmers from the world of command-line options, STDIN, and STDOUT, allowing them to build graphical, event-driven applications for both Windows and UNIX.This book is aimed at Perl ...

See more details below
Available through our Marketplace sellers.
Other sellers (Paperback)
  • All (31) from $1.99   
  • New (2) from $25.48   
  • Used (29) from $1.99   
Close
Sort by
Page 1 of 1
Showing All
Note: Marketplace items are not eligible for any BN.com coupons and promotions
$25.48
Seller since 2009

Feedback rating:

(872)

Condition:

New — never opened or used in original packaging.

Like New — packaging may have been opened. A "Like New" item is suitable to give as a gift.

Very Good — may have minor signs of wear on packaging but item works perfectly and has no damage.

Good — item is in good condition but packaging may have signs of shelf wear/aging or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Acceptable — item is in working order but may show signs of wear such as scratches or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Used — An item that has been opened and may show signs of wear. All specific defects should be noted in the Comments section associated with each item.

Refurbished — A used item that has been renewed or updated and verified to be in proper working condition. Not necessarily completed by the original manufacturer.

New
1565923146 *BRAND NEW* Ships Same Day or Next!

Ships from: Springfield, VA

Usually ships in 1-2 business days

  • Canadian
  • International
  • Standard, 48 States
  • Standard (AK, HI)
  • Express, 48 States
  • Express (AK, HI)
$60.00
Seller since 2014

Feedback rating:

(164)

Condition: New
Brand new.

Ships from: acton, MA

Usually ships in 1-2 business days

  • Standard, 48 States
  • Standard (AK, HI)
Page 1 of 1
Showing All
Close
Sort by
Sending request ...

Overview

Learning Perl/Tk is a tutorial for Perl/Tk, the extension to Perl for creating graphical user interfaces. With Tk, Perl programs can be window-based rather than command-line based, with buttons, entry fields, listboxes, menus, and scrollbars. Originally developed for the Tcl language, the Perl port of the Tk toolkit liberates Perl programmers from the world of command-line options, STDIN, and STDOUT, allowing them to build graphical, event-driven applications for both Windows and UNIX.This book is aimed at Perl novices and experts alike. It explains the reasoning behind event-driven applications and drills in guidelines on how to best design graphical applications. It teaches how to implement and configure each of the Perl/Tk graphical elements step-by-step. Special attention is given to the geometry managers, which are needed to position each button, menu, label and listbox in the window frame.Although this book does not teach basic Perl, anyone who has written even the simplest Perl program should be able to learn Tk from this book. The writing is breezy and informal, and gets right to the point of what you need to know and why. The book is rife with illustrations that demonstrate how each element is drawn and how its configuration options affect its presentation.Learning Perl/Tk is for every Perl programmer who would like to implement simple, easy-to-use graphical interfaces.


Trapped in a world of command-line options? With Tk, you can build programs for both UNIX and Windows platforms. Geared toward intermediate programmers, this new O'Reilly guide teaches the implementation and configuration of each Perl/TK graphical element. It details buttons, scrollbars, listboxes and text widgets. For each Perl/Tk widget discussed, the book includes common usage examples, configuration options and exercises.

Read More Show Less

Product Details

  • ISBN-13: 9781565923140
  • Publisher: O'Reilly Media, Incorporated
  • Publication date: 1/1/1998
  • Pages: 373
  • Product dimensions: 6.97 (w) x 9.13 (h) x 0.76 (d)

Meet the Author

Nancy Walsh has been involved with Perl (and Perl/Tk) since 1996. She received a Computer Science degree from the University of Arizona in 1993, and currently works as a Principal Consultant for XOR, Inc. doing J2EE and Java work on various projects. Nancy has taught several Perl/Tk Tutorials at the O'Reilly Open Source Conference and is also the author of Learning Perl/Tk.

Read More Show Less

Read an Excerpt


Chapter 5: Label and Entry Widgets Label Configuration

Label is a pretty boring widget, so there are only two methods available to change or get information on it: cget and configure. Both methods work for Label the same way they work for the Button widget. Please refer to Appendix A for the details on arguments and return values.

The Entry Widget

ENTRY WIDGET: Until now, the only input we know how to get from the input from a mouseclick is useful, but it's also limiting. The entry widget will let the user type in text that can then be used, in, any way by the application. Here are a few examples of where you might use an entry widget:

  • In a database form that requires one entry per field (e.g
  • In a software window that requires a serial number.
  • In a login window that requires a username and password
  • In a configuration window to get the name of a printer
  • In an Open File window that requires the path and name of a file

Normally, we don't care what users type in an entry widget until they are done typing, and any processing will happen "after the fact" when a user clicks some sort of Go button. You could get fancy and process each character as it's typed by setting up a complicated bind-but it is probably more trouble than it is worth.

The user can type anything into an entry widget. It is up to the programmer to decide if the text entered is valid or not. When preparing to use the information from an entry, we should do some error checking. If we want an integer and get some alphabetic characters, we should issue a warning or error message to the user.

An entry widget is a much more complex widget than it first appears to be. The entry widget is really a simplified one-line text editor. Text can be typed in, selected with the mouse, deleted, and added. I would classify an entry widget as a middle-of-the-line widget. It's more complicated than a button, but much less complicated than the text or canvas widgets.

Creating the Entry Widget No surprises here:

$entry = $parent->Entry( [ option => value . . . ] )->pack;

When the entry widget is created, it is initially empty of any text, and the insert cursor (if the entry had the keyboard focus) is at the far-left side.

Entry Options

The following list contains a short description of each option available for configuring an entry widget. Several of them are discussed in more detail later in this chapter.

-background => color

Sets the background color of the entry widget. This is the area behind the text.

-borderwidth => amount

Changes the width of the outside edge of the widget. Default value is 2.

-cursor => cursorname

Changes the cursor to cursorname when it is over the widget.

-exportselection => 0 1 1

If the Boolean value specified is true, any text selected will be exported to the windowing system's clipboard.

-font => fontname

Changes the font displayed in the entry to fontname.

-foreground => color

Changes the color of the text.

-highlightbackground => color

Sets the color the highlight rectangle should be when the widget does not have the keyboard focus.

-highlightcolor => color

Sets the color the highlight rectangle should be when the widget does have the keyboard focus.

-highlightthickness => amount

Sets the thickness of the highlight rectangle around the widget. Default is 2.

-insertbackground => color Sets the color of the insert cursor.

-insertborderwidth => amount

Sets the width of the insert cursor's border. Normally used in conjunction with

-ipadx and -ipady options for the geometry manager.

-insertoff time => milliseconds

Sets the amount of time the insert cursor is off in the entry widget.

-insertontime => milliseconds

Sets the amount of time the insert cursor is on in the entry widget.

-insertwidth => amount

Sets the width of the insert cursor. Default is 2.

-justify => left, 1 'right' 1 'center'

Sets the justification of the text in the entry widget. The default is left.

-relief => flat, 1 'groove, 1 raised, 1 ridge, sunken,

Sets the relief of the outside edges of the entry widget.

-selectbackground => color

Sets the background color of any selected text in the entry widget.

-selectborderwidth => amount

Sets the width of the selection highlight's border.

-selectforeground => color

Sets the text color of any selected text in the entry widget.

-show => char

Sets the character that should be displayed instead of the actual text typed.

-state => 'normal' 1 disabled, 1 active,

Indicates the state of the entry. Default is 'normal'

-takefocus => 0 1 1 1 undef

Allows or disallows this widget to have the keyboard focus.

-textvariable => \$variable

Sets the variable associated with the information typed in the entry widget.

-width => amount

Sets the width of the entry in characters.

-xscrollcommand => callback Assigns a callback to use when scrolling back and forth.

The following options behave as we expect them to, and aren't worth further discussion: - background, -cursor, -font, -highlightbackground, -highlightcolor, -highlightthickness, -foreground, - justify, -takefocus, and -state. For more detailed information on these how these options affect a widget, see Chapter 3.

Assigning the Entry's Contents to a Variable

The -textvariable option lets you know what the user typed in the entry widget:

-textvariable => \$variable

By now, you should be familiar with this option from several of our button examples. Any text input into the entry widget will get assigned into $variable. The reverse also applies. Any string that gets assigned to $variable will show up in the entry widget.

It is important to remember that no matter what the user enters, it will be assigned to this variable. This means that even though you are expecting numeric input (e.g., "314"), you might get something like "3s14" if the user accidentally (or on purpose!) presses the wrong key(s). Before using any information from an entry widget, it's a good idea to do some error checking to make sure it's the information you expect or, at the very least, in the correct format. Trying to use "3s14i" in an equation would most likely produce undesired results.

The other way you can find out what is in the entry widget is by using the get method:

$stuff = $entry->geto;

You can use get whether or not you have used the -textvariable option....

Read More Show Less

Table of Contents

Preface;
What You Should Already Know;
What’s in This Book;
Reading Order;
Typographical Conventions;
We’d Like to Hear from You;
Acknowledgments;
Chapter 1: Introduction to Perl/Tk;
1.1 A Bit of History About Perl (and Tk);
1.2 Perl/Tk for Both Unix and Windows 95/NT;
1.3 Why Use a Graphical Interface?;
1.4 Why Use Perl/Tk?;
1.5 Installing the Tk Module;
1.6 Creating Widgets;
1.7 Coding Style;
1.8 Displaying a Widget;
1.9 The Anatomy of an Event Loop;
1.10 Hello World Example;
1.11 Using exit Versus Using destroy;
1.12 Naming Conventions for Widget Types;
1.13 Using print for Diagnostic/Debugging Purposes;
1.14 Designing Your Windows (A Short Lecture);
Chapter 2: Geometry Management;
2.1 Pack;
2.2 Grid;
2.3 Place;
2.4 Geometry Management Summary;
Chapter 3: The Basic Button;
3.1 The Button Widget;
3.2 Some Fun Things to Try;
Chapter 4: Checkbuttons and Radiobuttons;
4.1 The Checkbutton Widget;
4.2 The Radiobutton Widget;
4.3 Fun Things to Try;
Chapter 5: Label and Entry Widgets;
5.1 The Label Widget;
5.2 The Entry Widget;
5.3 Fun Things to Try;
Chapter 6: Scrollbars;
6.1 Defining Scrollbar Parts;
6.2 The Scrolled Method;
6.3 The Scrollbar Widget;
6.4 Examples;
6.5 Fun Things to Try;
Chapter 7: The Listbox Widget;
7.1 Creating and Filling a Listbox;
7.2 Listbox Options;
7.3 Selection Modes;
7.4 Colors;
7.5 Listbox Style;
7.6 Configuring a Listbox;
7.7 Inserting Items;
7.8 Deleting Items;
7.9 Retrieving Elements;
7.10 Selection Methods;
7.11 Moving to a Specific Index;
7.12 Translating Indexes;
7.13 Counting Items;
7.14 Active Versus Selected;
7.15 Bounding Box;
7.16 Finding an Index by Y Coordinate;
7.17 Scrolling Methods;
7.18 Listbox Example;
7.19 Fun Things to Try;
Chapter 8: The Text Widget;
8.1 Creating and Using a Text Widget;
8.2 Text Widget Options;
8.3 A Short Break for a Simple Example;
8.4 Text Indexes;
8.5 Text Tags;
8.6 Inserting Text;
8.7 Deleting Text;
8.8 Retrieving Text;
8.9 Translating Index Values;
8.10 Comparing Index Values;
8.11 Showing an Index;
8.12 Getting the Size of a Character;
8.13 Getting Line Information;
8.14 Searching the Contents of a Text Widget;
8.15 Scrolling;
8.16 Marks;
8.17 Embedding Widgets;
8.18 Internal Debug Flag;
8.19 Fun Things to Try;
Chapter 9: The Canvas Widget;
9.1 Creating a Canvas;
9.2 Coordinate System;
9.3 The Scrollable Region;
9.4 Using Bind with a Canvas;
9.5 Canvas Options;
9.6 Creating Items in a Canvas;
9.7 Configuring the Canvas Widget;
9.8 Configuring Items in the Canvas Widget;
9.9 Tags;
9.10 Retrieving Bounding Box Coordinates;
9.11 Translating Coordinates;
9.12 Moving Items Around;
9.13 Changing the Display List;
9.14 Deleting Items;
9.15 Deleting Tags;
9.16 Determining Item Type;
9.17 Set Keyboard Focus;
9.18 Rendering the Canvas as PostScript;
9.19 Scaling the Canvas;
9.20 Scanning;
9.21 A Drawing Program Example;
9.22 Fun Things to Try;
Chapter 10: The Scale Widget;
10.1 Creating a Scale;
10.2 Assigning a Callback;
10.3 Orientation;
10.4 Minimum and Maximum Values;
10.5 Displayed Versus Stored Value;
10.6 Adding a Label;
10.7 Displaying Value Increments;
10.8 Changing the Size of the Scale;
10.9 Options You’ll Probably Never Need;
10.10 Configuring a Scale;
10.11 Getting the Value of a Scale;
10.12 Setting the Value of a Scale;
10.13 Determining Coordinates;
10.14 Identifying Parts of a Scale;
10.15 Fun Things to Try;
Chapter 11: Menus;
11.1 Different Types of Menus;
11.2 The Menubutton Widget;
11.3 Complete Menubutton Examples;
11.4 The Menu Widget;
11.5 Optionmenu Widget;
11.6 Fun Things to Try;
Chapter 12: Frames;
12.1 Creating a Frame;
12.2 Frame Style;
12.3 Frames Aren’t Interactive;
12.4 Colormap Complications;
12.5 Frame Methods;
12.6 Fun Things to Try;
Chapter 13: Toplevel Widgets;
13.1 Creating a Toplevel Widget;
13.2 Toplevel Methods;
13.3 Review;
13.4 Fun Things to Try;
Chapter 14: Binding Events;
14.1 The bind Method;
14.2 Arguments Sent to the Callback;
14.3 Defining Event Sequences;
14.4 Event Information;
14.5 Bailing Out of a Callback Created with bind;
14.6 The bindtags Method;
14.7 Ways to Use bind;
Chapter 15: Composite Widgets;
15.1 Looking at an Example Sideways;
15.2 Location of Files;
15.3 Creating a Composite Widget Based on Frame;
15.4 Toplevel-Based Composite Widgets;
Chapter 16: Methods for Any Widget;
16.1 Building a Family Tree;
16.2 Color-Related Methods;
16.3 Option Databases;
16.4 The Application’s Name;
16.5 Widget Existence;
16.6 Is the Widget Mapped?;
16.7 Converting Screen Distances;
16.8 Size of Widget;
16.9 Widget Position;
16.10 Screen Information;
16.11 Atom Methods;
16.12 Ringing a Bell;
16.13 Clipboard Methods;
16.14 Selection Methods;
16.15 Destroying a Widget;
16.16 Focus Methods;
16.17 Grab Methods;
16.18 Interapplication Communication;
16.19 Waiting for Events to Happen;
16.20 Parsing Command-Line Options;
16.21 Time Delays;
Configuring Widgets with configure and cget;
The configure Method;
Default Values for Each Widget in Table Form;
Operating System Differences;
Unix;
Windows NT and 95;
Fonts;
The Font String;
Font Methods;
Colophon;

Read More Show Less

First Chapter


Chapter 2: Geometry Management

To allow widgets to be displayed on the screen, they must be passed to a geometry manager. The geometry manager controls the position and size of the widgets in the display window. There are several geometry managers available with Perl/Tk: pack , place , and grid .

All three geometry managers are invoked as methods on the widget, but they all have their own methodologies and arguments to change where and how the widgets are put on the screen:



When you organize the widgets in your window, it is often necessary to separate groups of widgets to get a certain look and feel. For instance, when you use pack() , it is difficult to have widgets stacked both horizontally and vertically without grouping them in some fashion. We group the widgets together by using a frame widget inside a window or by using another window (a toplevel widget).

We create our first window by calling MainWindow . The MainWindow is a special form of a toplevel widget. For more detailed information on how to create/configure frames and toplevel widgets, see , and .

Because of the differences between the three geometry managers, it is difficult (not entirely impossible, but definitely not recommended) to use more than one geometry manager within the same area. In our $mw I can place many types of widgets, but if I start using pack() , I should continue to use pack() on all of the widgets contained directly in $mw . I wouldn't want to switch in the middle to using grid() . Because a window can contain a frame, which in turn contains other widgets, we use pack() to pack the frame inside the main window and then we could use grid() to manage the widgets inside the frame. See Figure 2-1.

Figure 2-1. Frame within a window that uses a different geometry manager

Although the different geometry managers have their own strengths and weaknesses, the most commonly used is pack() , so we discuss it first and in the most detail. The grid() geometry manager was under development as I was writing this book. grid has been improved greatly with the release of Tk 8.0 and subsequent porting to Perl. The place() geometry manager is the most tedious to use because you have to determine exact coordinates for every single widget.

Pack

Remember when you were a small child and you had those wooden puzzles to put together? They often had cute little pictures of animals on them. Each piece in the puzzle had exactly one place where it could go, and there weren't any overlaps allowed between pieces.

With the pack geometry manager, our windows are similar to the wooden puzzle because widgets cannot overlap or cover each other (partially or completely). See Figure 2-2. If a button is packed in a certain space on the window, the next button (or any widget) will have to move around the already packed button. Luckily, our windows will only be dealing with rectangular shapes instead of funny-shaped puzzle pieces.

Figure 2-2. Overlap error

The order in which you pack your widgets is very important because it directly affects what you see on the screen. Each frame or toplevel maintains a list of items that are displayed within it. This list has an order to it; if widget A is packed before widget B, then widget A will get preference. This will become clear as we go through some examples. You will often get a very different look to your window just by packing the widgets in a different order.

If you don't care what the window looks like and how the widgets are put in it, you can use pack() with no arguments and skip the rest of this chapter. Here it is again:



To make your window look nicer and more manageable (and user friendly), there are arguments that can be sent to the pack method that will change the way the widgets and the window looks. As with anything in Perl/Tk, the arguments are arranged in pairs. So the more sophisticated usage would be:



Here is the code to create a window that doesn't use any options to pack() Figure 2-3 shows the resulting window (I know we haven't covered all the widgets used in this example, but hang in there, it's pretty simple).





 







 













Figure 2-3. Window with widgets managed by pack

We can alter the preceding code and add some options to the pack() calls that will make our window look much nicer:





 







 























Figure 2-4 shows the much more organized window.

Figure 2-4. Window with widgets managed by pack

Using pack() allows you to control:

  • Position in the window relative to the window or frame edges
  • Size of widgets, relative to other widgets or absolute
  • Spacing between widgets
  • Position in the window's or frame's widget list

The options, values, and defaults are listed and discussed in the following section.

Pack Options

This list shows all the options available when you call pack() . The default values are shown in bold (which indicates if you don't use that option, you'll get the effects of that value for that option).

-side => 'left' | 'right' | 'top' | 'bottom'
Puts the widget against the specified side of the window or frame
-fill => ' none ' | 'x' | 'y'| 'both'
Causes the widget to fill the allocation rectangle in specified direction
-expand => 1 | 0
Causes the allocation rectangle to fill remaining space available in window or frame
-anchor => 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | ' center '
Anchors the widget inside the allocation rectangle
-after => $otherwidget
Puts $widget after $otherwidget in packing order
-before => $otherwidget
Puts $widget before $otherwidget in packing order
-in => $otherwindow
Packs $widget inside of $otherwindow rather than the parent of $widget , which is the default
-ipadx => amount
Increases the size of the widget horizontally by amount x 2
-ipady => amount
Increases the size of the widget vertically by amount x 2
-padx => amount
Places padding on the left and right of the widget
-pady => amount
Places padding on the top and bottom of the widget

Positioning Widgets

Each window (or frame) has four sides to it: top, bottom, left, and right. The packer uses these sides as points of reference for widgets. By default, pack() places the widgets against the top of the toplevel or frame.

You can control what side a widget is placed against by using the -side option:



For example, if we would like our button against the left edge of the window, we can specify -side => ' left '.

Using our Hello World example as a base, let's look at what happens when we pack our button against the different sides. The only line we will change is the ->pack part of the Button creation line. We'll also change the "Hello World" string in the $mw->title command to easily show the new options to pack.

$mw->Button(-text => 'Done',

-command => sub { exit })

->pack(-side => 'top');

OR

$mw->Button(-text => 'Done',

-command => sub { exit })

->pack;

 

$mw->Button(-text => 'Done',

-command => sub { exit })

->pack(-side => 'bottom');

 

$mw->Button(-text => 'Done',

-command => sub { exit })

->pack(-side => 'left');

 

$mw->Button(-text => 'Done',

-command => sub { exit })

->pack(-side => 'right');

 

The windows shown here have been made a bit larger to emphasize the difference that using alternative values for -side makes. Normally, the window will be only as large as required to show the button. When you are deciding which way to place widgets in a window, it is always a good idea to see what happens when you make the window both larger and smaller. Make sure the behavior you get is what you want.

So far, pack() seems pretty simple, but what if you want to put more than one button in your application? What happens when we simply add more buttons?









Since the default -side is top , we would expect them to all be mushed up against the top of the window, right? Sort of. The packer allocates space for each widget and then manipulates the widget inside that space and the space inside the window.

Figure 2-5 shows what the window with the four Done buttons looks like; the next section explains why.

Figure 2-5. Four buttons packed with default settings

Allocation Rectangles

When given an item to pack, the packer first looks to see which side (top, bottom, right, or left) to use. It then sets aside an invisible rectangular area across the length of that side for use only by that widget.

In Figure 2-6 , the solid-line rectangle represents our empty window (or frame), and the dotted-line rectangle is the rectangular area that the packer sets aside for the first button. It actually does go all the way across the width or height of the window, but to make it easier to see, it's shown a little indented.

Figure 2-6. Rectangular areas set aside by packer when using -side => `top' and -side => `left'

The dimensions for the dotted-line box, which we'll call the allocation rectangle, are calculated based on the size of the requesting widget. For both the top and bottom sides, the allocation rectangle is as wide as the window and only as tall as the widget to be placed in it. For the right and left sides, the allocation rectangle is as tall as the window but only as wide as required to fit the widget.

Our examples so far have used buttons in which the text of the button determines the width of the button. If we create a button with the text "Done" on it and one with the text "Done, Finished, That's it," the second button is going to be much wider than the first. When these two buttons are placed up against either the right or left side of the window, the second button would have a wider allocation rectangle than the first. If we placed those same two buttons against the top and the bottom, the allocation rectangles would be the same height and width, that of the widest button.

After the size of the allocation rectangle is determined, the widget is placed within the allocation rectangle according to other options passed and/or the default values of those options. I will go over those options and how they can affect the allocation rectangle later.

Once the first widget has been placed in the window, the amount of area available for subsequent allocation rectangles is smaller because the first allocation rectangle has used some of the space (see Figure 2-7 ).

Figure 2-7. Second allocation rectangle when default side 'top' is used

When more than one button is placed against different sides in the same window, the results will vary depending on the order used.

We'll start by placing one button along the top, one along the bottom, and then buttons right and left:























The allocation rectangles for this window would look like the diagram in Figure 2-8 .

Figure 2-08.Allocation rectangles for four buttons

Figure 2-9 shows what the actual window looks like, both normal size and resized so it's a bit larger.

Figure 2-09.Four buttons placed around the sides of the window

Filling the Allocation Rectangle

Normally, the widget is left at the default size, which is usually smaller than the allocation rectangle created for it. If the -fill option is used, the widget will resize itself to fill the allocation rectangle according to the value given. The possible values are:



Using the value 'x' will resize the widget in the x direction. Likewise, 'y' will cause the widget to resize in the y direction. Using -fill => 'both' is a good way to see exactly what size and placement was given to the allocation rectangle because 'both' resizes the widget in both x and y directions. Using our four-button example again, we'll specify -fill => 'both' .























Figure 2-10 shows the resulting window.

Figure 2-10. Four buttons packed to each side using -fill => 'both'

If we switch the button we create first, we get a different result. The window in Figure 2-11 was created by packing the widgets in this order: left, right, top, bottom.

Figure 2-11. Four buttons packed to each side in a different order using -fill => 'both'

Figure 2-12 demonstrates yet another order, which really shows that the allocation rectangles change size depending on what gets packed first.

Figure 2-12. Four buttons packed in order of top, right, bottom, and left

A common use of -fill is on widgets with scrollbars: listbox, canvas, and text. Usually, the scrollbars are along the edge of the window, and you want the listbox to fill the remaining area. See Chapter 6, Scrollbars, and Chapter 7, The Listbox Widget, for more information.

Expanding the Allocation Rectangle

The -expand option manipulates the allocation rectangle and not the widget inside it. The value associated with -expand is a Boolean value.



Given a true value, the allocation rectangle will expand into any available space left over in the window depending on which side the widget was packed.

Widgets packed with side right or left will expand in the horizontal direction. Widgets packed with side top or bottom will expand in the vertical direction. If more than one widget is packed with -expand turned on, the extra space in the window is divided evenly among all the allocation rectangles that want it.

In Figure 2-9 or Figure 2-10 , you saw that there was some space left in the center of the window that wasn't occupied by any widget. If we change the code and add -expand => 1 to the list of pack options for each button, the result is the window in Figure 2-13 .

Figure 2-13. Four buttons using the -expand => 1 and -fill => `both' options

Note that Figure 2-13 left the -fill => 'both' option in the code. If we omit the -fill option, the buttons stay their original size, but the allocation rectangles (which are invisible) have taken over the extra space in the window.

Figure 2-14. Four buttons using -expand => 1 and -fill => `none'

The buttons are centered in their allocation rectangles because of the default value of the -anchor option, which is 'center' .

Anchoring a Widget in Its Allocation Rectangle

The anchor option manipulates the widget inside the allocation rectangle by anchoring it to the place indicated by the value passed in. It uses the points of a compass as a reference.



Figure 2-15 shows those locations in an example allocation rectangle.

Figure 2-15. Allocation rectangle with -anchor points labeled

The default for -anchor is 'center' , which keeps the widget in the center of its allocation rectangle. Unless the -expand option is set to a true value, this won't seem to change much of anything in the window. As seen in Figure 2-16 , which shows the result of using the -expand => 1 option, it is obvious that the widget sticks to that center position when the window is resized.

Figure 2-16. Default behavior of -anchor with -expand set to 1

If all other defaults are used to pack the widget, Figure 2-17 shows what -anchor => 'e' and -anchor => 'w' does.

Figure 2-17. Examples of -anchor => `e' and -anchor => `w'

Remember that the allocation rectangle is created based on which side the widget is packed against, so certain combinations will appear to have not had any effect. For example:





This code fragment will leave the widget exactly where it was if the -anchor option had not been specified because the allocation rectangle does not change size at all. If the -expand option is also specified, then when the window is resized, the widget would stick to the north side of the window. If -anchor => 's' had been specified, when the window is resized, the widget would stick to the south side of the window.

The -anchor option is more often used to line up several widgets in a row. Figure 2-18 and Figure 2-19 are two common examples.

Figure 2-18. Window with three buttons all packed with -side => `top', -anchor => `w'

Figure 2-19. Windows with three buttons all packed with -side => `left', -anchor => `n'

Sometimes, when -side and -anchor are used together, the results don't seem to be what you would expect at first glance. Always keep in mind that invisible allocation rectangle and how it affects what you see on the screen.

Widget Order in the Window

Each window that has widgets packed into it keeps track of those widgets in an ordered list. The order of this list is normally determined by the order in which the widgets were packed. The last item packed is the last item in the list. Using the -after option, you can change the default order by specifying which widget should be placed after your new widget. On the opposite end, if you use the -before option, you can put the new widget before a previously packed widget:





As an example, let's create four buttons ( $widget1 , $widget2 , $widget3 , $widget4 ) and only pack three to begin with. The pack command for $widget4 might then be:



Figure 2-20 shows two windows: one before $widget4 is packed and one after $widget4 is packed.

Figure 2-20. On left: the window with three buttons packed in order. On right: the button with Done4 label was packed using -after => $widget1

If we want to put $widget4 in front of $widget1 , we use this command:



Figure 2-21 contains the results of using the -before option.

Figure 2-21. Button with Done4 label was packed using -before => $done1

Padding the Size of the Widget

The final way to force pack() to size the widget is to use the padding options. The first set of padding options affects the widget itself by adding to its default size. Different amounts can be added in the x and y direction, or they can be the same. To specify how much padding should occur in the x direction, use the -ipadx option:



Specify padding for the y direction like this:



The amount is a number that is a valid screen distance. I'll discuss the definition of a valid screen distance in the next section.

Both the -ipadx and -ipady options change the size of the widget before the allocation rectangle is calculated. -ipadx adds the amount specified to both the right and left sides of the widget. The overall width of the widget would increase by (2 x amount ). -ipady adds to the top and bottom of the widget, causing the overall height of the widget to increase by (2 x amount ). Figure 2-22 shows how the -ipadx and -ipady options affect a button.

Figure 2-22. The Done1 button was created with options: -ipadx => 10, -ipady => 10

The other kind of padding is inserted between the edge of the widget and the edge of the allocation rectangle and is done with the -padx and -pady options:





Using -padx and -pady does not affect the size of the widget, but it does affect the size of the allocation rectangle. It acts as a buffer around the widget, protecting it from having to touch other widgets. Figure 2-23 shows the affects of using -padx and -pady .

Figure 2-23. The Done1 button was created with options -padx => 10, -pady => 10

A good way to remember the difference between -ipadx/y and -padx/y is that the "i" stands for "inside the widget" or "internal padding."

Valid screen distances

Many times you'll see options that require values specified in screen units (or called a valid screen distance). The options -ipadx and -ipady are examples of this type of option. Always check to see what value the option actually requires.

A screen unit is a number followed by a designation for the unit to use. If there is no designation, the units are in pixels. Table 2-1 shows all the possibilities.

 
Valid screen units

Designator

Meaning

Examples

(none)

Pixels (default)

20 , 30 , "20" , "40"

c

Centimeters

'3c' , '4c' , "3c"

i

Inches

'2i' , "3i"

m

Millimeters

'4m' , "4m"

p

Printer points (1/72 inch)

"72p" , '40p'

To use these designators, it is necessary to use quotes (either single or double) around the value. Here are some examples:













Remember that a "p" designator does not stand for pixels, but printer points. I recommend always using pixels as your unit of measure. Different screens display different resolutions; one screen might display an actual inch and another might display something else.

Displaying in a Parent Other Than Your Own

By default, when a widget is packed, it is packed inside the region that created it. Sometimes it is necessary to display a widget inside a different region. Use the -in option to do so:



It puts the new widget at the end of the packing order for the $otherwindow and displays it accordingly. All other options specified in the pack() call still apply.

Methods Associated with Pack

There are a few methods that are used in conjunction with the pack geometry manager. They allow the programmer to get information about either the widget that has been packed or the parent widget in which other widgets are packed.

Unpacking a widget

To unpack a widget from a window or frame, use the packForget method:



packForget makes it look like the widget disappears. The widget is not destroyed, but it is no longer managed by pack. The widget is removed from the packing order, so if it were repacked later, it would appear at the end of the packing order.

Retrieving pack information

To return a list containing all the pack-configuration information about a widget, use packInfo <%%>



The format of the list is in option/value pairs. The first pair in the list is -in and the current window that contains $widget (usually also the parent). This is an example of the information returned from packInfo <%%>



From this, we can tell that we packed our $widget into the main window, rather than a frame. Since the list has a "paired" quality to it, we could easily store the result from packInfo in a hash and reference the different option values by using a key to the hash:





Disabling and enabling automatic resizing

When you put a widget inside a window, the window (or frame) will resize itself to accommodate the widget. If you are dynamically placing widgets inside your window while the program is running, the window will seem to bounce from size to size. You can turn off this behavior by using packPropagate on the frame or toplevel widget:



If set to 0 or 'off' , packPropagate changes the behavior of the widget so that it doesn't resize to accommodate items packed inside of it. When a false value is sent to packPropagate before widgets are placed inside it, this automatic resizing doesn't happen, so you can't see any of the widgets placed inside the parent until it is manually resized. If you call packPropogate after the widgets have been placed inside it, the widget will ignore any size changes from its child widgets.

Listing widgets

You can determine the widgets your frame or toplevel holds by using the packSlaves method:



packSlaves returns an ordered list of all the widgets that were packed into the $parentwidget . An empty string (or empty list) is returned if no widgets were packed into $parentwidget .

The list returned from packSlaves looks like this:



Each item is a reference to a packed widget and can be used to configure it. For example, you can increase the size of each widget by 20 in both the x and y directions by looping through it and "packing" it with new information. Using our good window example in Figure 2-4 , we can add a button that will contain a subroutine that uses packSlaves <%%>



















Figure 2-24 shows the resulting window.

Figure 2-24. Window before pressing Enlarge button

Let's look at what happens when we press the Enlarge button. As shown in Figure 2-25 , all the widgets are now repacked with additional parameters of -ipadx => 20, -ipady => 20 . These new options are in addition to any other parameters the widgets were packed with before.

Figure 2-25. Window after pressing Enlarge button

The window is suddenly huge! Subsequent presses of the Enlarge button will do nothing more to the window because all the widgets already have an -ipadx and -ipady of 20. If we wanted to always add twenty to the values of -ipadx and -ipady , we would have to request the current values and add 20 to them. Here's the code for that:

















We use packInfo to get the current configuration and add 20 to that value.

Grid

The grid geometry manager divides the window into a grid composed of columns and rows starting at 0,0 in the upper left-hand corner. Figure 2-26 shows a sample grid.

Figure 2-26. Diagram showing window divided into grid

Rather than using the sides of a window as reference points, grid() divides the screen into columns and rows. It looks a lot like a spreadsheet doesn't it? Each widget is assigned a grid cell using the options available to grid() .

The grid() method takes a list of widgets instead of operating on only one widget at a time . Here is the generic usage:



A specific example:



Instead of using three separate call, you can use one grid() call to display all three widgets, . You can also invoke grid() on each window independently just as you can pack() . Each call to grid() will create another row in the window. So in our example,: $widget1 , $widget2 , and $widget3 will be placed in the first row. Another call to grid would create a second row. This is what happens when you do not specify any additional options to the grid() call.

For greater control, you can specify explicit -row and -column options for each widget in the window. I will cover these options later.

These assumptions are made when additional options are not specified:

  • The first widget in the row (for example, $widget1 in the preceding example) invokes the grid() command.
  • All remaining widgets for that row will be specified within the grid() command.
  • Each additional call to grid() will add another row to the display.
  • Special characters can be used to change the -columnspan and -rowspan of the widget.

A few examples will help demonstrate. Each call to grid() will create another row, so we know we have two rows in the following example:







In this example, we have created four rows and there is only one widget in each row:











We can also create widgets as we go:









Pay careful attention because the second, third, and fourth calls to Button are inside the call to grid() . All four of the buttons will be placed in the first row. If we executed the same exact command again, the new widgets would be placed in the next row.

Special Characters

There are several special characters that can be used to alter the way the widgets are gridded in the window. Each special character serves as a type of placeholder that indicates what to do with that position in the grid:

"-" (a minus sign)
Tells grid that the widget specified right before this one in the list should span this column as well. To span more than one column, place a "-" in each widget position to span. A "-" may not follow a "^" or an "x"
"x"
Effectively leaves a blank space where a widget would otherwise be placed.
"^"
A widget in row x will span row x and x + 1 when this character is placed in the grid command for row x + 1 in that row/column position. The number of "^" characters must match the number of columns the widget spans in row x . Similar to "-" , but goes down, not across.

The following sections include some examples that illustrate what the special characters do.

Spanning columns

The following bit of code creates three rows of buttons. The first two rows are normal, and in the third, the second button spans three columns. Each "-" character adds one to the number of columns the button uses, and the default is 1. So the original column and two hyphens ( "-" , "-" ) indicate that there are three rows to span. The -sticky option is necessary for the widgets to stick to the sides of the cells it spans. If the -sticky option had been left out, the button would be centered across the three cells it spans.





























The resulting window is shown in Figure 2-27 .

Figure 2-27. Example of column spanning using the "-" character

Empty cells

The "x" character translates to "skip this space" and leaves a hole in the grid. I removed the line that created Button6 and replaced it with an "x" in the following code. The cell for it is still there, it just doesn't contain a widget.



















The resulting window is shown in Figure 2-28 .

Figure 2-28. Leaving an empty cell between widgets

Grid Options

The rest of the options are similar to those used with pack() <%%>

"-"
Special character used in grid widget list. Increases columnspan of widget prior to it in widget list.
"x"
Special character used in grid widget list. Leaves a blank space in the grid.
"^"
Special character used in grid widget list. Increases rowspan of the widget in the grid directly above it.
-column => n
Sets the column to place widget in ( n >= 0).
-row => m
Sets the row to place widget in ( m >= 0).
-columnspan => n
Sets the number of columns for the widget to span beginning with -column
-rowspan => m
Sets the number of rows for the widget to span beginning with -row
-sticky => string
String contains characters n , s , e , or w . Widget will stick to those sides.
-in => $otherwindow
Indicates that widget is gridded inside $otherwindow instead of parent of $widget
-ipadx => amount
$widget becomes larger in x direction by 2 x amount
-ipady => amount
$widget becomes larger in y direction by 2 x amount
-padx => amount
Buffer space equal to amount is placed to left and right of widget.
-pady => amount
Buffer space equal to amount is placed on top and bottom of widget.

Explicitly Specifying Rows and Columns

Rather than letting grid() make assumptions, it is sometimes necessary to explicitly state the row and column in which the widget should be placed. This is done by using the -row and -column options. Each option takes a nonnegative integer as an argument:



When you use -row and -column , it is not necessary to build or grid() the widgets in any sort of logical order (except for your own sanity when you are debugging). You could place your first widget in column 10 and row 5 if you like. All of the other cells with lower row and column values will remain empty.

Explicitly Spanning Rows and Columns

It is also possible to explicitly indicate that a widget (or widgets) should span some columns or rows. The option to use to span columns is -columnspan . For spanning rows, the option is -rowspan . Both options take an integer that is 1 or greater. The value indicates how many rows or columns should be spanned, including the row or column in which the widget is placed.

For this example, I have used the easy way to place widgets in columns and rows by not explicitly specifying the -row and -column options. Note that the second grid command applies to two button widgets, so the single -columnspan option applies to both buttons created there.





















The resulting window is shown in Figure 2-29 .

Figure 2-29. -columnspan example

This window could also have been created using the "-" special character to indicate column spanning, like this:





















This example illustrates how to explicitly use the -row and -column options in addition to the -rowspan option:































See Figure 2-30 for the resulting window.

Figure 2-30. Explicit -rowspan example

Forcing a Widget to Fill the Cell

When you use the pack() command, it is necessary to indicate both -fill and -expand options to get the widget to resize inside its allocation rectangle. The grid() command doesn't have an allocation rectangle to fill, but it does have the cell within the grid. Using the -sticky option with grid() is similar to using -fill and -expand with pack() .

The value associated with -sticky is a string containing the compass points to which the widget should "stick." If the widget should always "stick" to the top of the cell, you would use -sticky => "n" . To force the widget to fill the cell completely, use -sticky => "nsew" . To make the widget as tall as the cell but only as wide as it needs to be, use -sticky => "ns" . The string value can contain commas and whitespace, but they will be ignored. These two statements are equivalent:





If you use -sticky with your widgets and then resize the window, you'll notice that the widgets don't resize as you think they should. They don't because resizing of the cells and the widgets in them is taken care of with the gridColumnconfigure and gridRowconfigure methods, which are discussed later in this chapter.

Padding the Widget

grid() also accepts these four options: -ipadx , -ipady , -padx , -pady . They work exactly the same as they do in pack() , but instead of affecting the size of the allocation rectangle, they affect the size of the cell in which the widget is placed.

In this example, the -ipady and -ipadx options are applied to the top row of buttons and not the bottom row. Notice in Figure 2-31 how Buttons 5 through 8 are also wider than they really need to be. This is because we used the -sticky => "nsew" option.























Figure 2-31. grid -ipadx and -ipady example

In this example, the -pady and -padx options are applied to the top row of buttons and not the bottom row. Figure 2-32 shows the results.























Figure 2-32. grid -padx and -pady example

Specifying a Different Parent

The -in option works the same way it does in pack() . The $widget will be placed in $otherwindow and not in the default parent of $widget . Here is the usage:



Configuring Columns and Rows

As with any of the geometry managers, grid has a few methods that are associated with it. Each method is invoked via a widget that has been placed on the screen by using grid() . Sometimes it is necessary to change the options of the group of cells that makes up your grid.

You can control resizing and the minimum size of a cell with the gridColumnconfigure and gridRowconfigure methods. Each takes a column or a row number as its first argument and then takes some optional arguments that will change the configuration of that column or row.

Both gridColumnconfigure and gridRowconfigure work very similar to the configure method used with widgets. Unlike the configure method used with widgets, however, the options you can specify with gridColumnconfigure and gridRowconfigure cannot be used with the grid() command. The options you can use with gridColumnconfigure and gridRowconfigure are -weight , -minsize , and -pad .

If you send only a row or column number, an array is returned with the current options and their values for that method:





In this example, we are getting the options and their values for the first column and the first row. The results of using the default values would look like this:





You can get the value of only one of the options by sending that option as the second argument:





The results would be:





To change the value of the options, use the option and then the value you want associated with it immediately after the option; for example:





You can also specify multiple options in one call:





Now that we know how to call gridColumnconfigure and gridRowconfigure , we need to know what the three different options do.

Weight

The -weight option sets how much space is to be allocated to that column or row when the window is divided into cells. Remember to use -sticky => "nsew" in your grid() command if you want the widget to resize when the cell does. The default -weight is 0, which causes the column width or row height to be dictated by the largest widget in the column. Each -weight value has a relationship to the other -weight s in the rows or columns.

If a column or row has a -weight of 2, it is twice as big as a column or row that has a -weight of 1. Columns or rows of -weight 0 don't get resized at all. If you want all your widgets to resize in proportion to the size of the window, add this to your code right before you call MainLoop <%%>















This code will assign the -weight of 1 to every single row and column in the grid, no matter what size the grid is. Of course, this method only works if you want to assign the same size to each row and each column, but you get the idea.

Here is an example of how the -weight option works ( Figure 2-33 shows the result):





























By giving row 1 and column 1 a weight of 1 (whereas all other rows and columns have 0 weight), they take over any extra available space when the size of the window is increased. Notice that columns 0, 2, and 3 are only as wide as is necessary to draw the buttons and their text, but column 1 has filled in the extra space. The same effect happens for row 0 with a weight of 0 and row 1 with a new weight of 1. (The window has been resized larger to demonstrate the effects of -weight )

Figure 2-33. gridRowconfigure and gridColumnconfigure example

Minimum cell size

The option -minsize sets the smallest width for the column or the smallest height for each row. The - minsize option takes a valid screen distance as a value. In this example, the minimum size of the cells in row 0 and column 0 is set to 10 pixels:





If the column or row was normally less than 10 pixels wide, then it would be forced to be at least that large.

Padding

You can add padding around the widget and to the widget by using the -padx/y and -ipadx/y options. You can also add a similar type of padding by using the -pad option with the gridColumnconfigure and gridRowconfigure methods. The padding is added around the widget, not to the widget itself. When you call gridColumnconfigure , the -pad option will add padding to the left and right of the widget. Calling gridRowconfigure with -pad will add padding to the top and bottom of the widget. Here are two examples:





Bounding box

To find out how large a cell is, you can use the gridBbox method:



This example gets the bounding box for column 0 and row 2. All the values returned are in pixels. The bounding box will change as you resize the window. The four values returned represent the x offset, the y offset, the cell width, and the cell height (offsets are relative to the window where the widget is gridded).

Removing a Widget

Like packForget , gridForget causes the widget(s) to be removed from view on the screen. This may or may not cause the window to resize itself; it depends on the size of $widget and where it was on the window. Here are some examples:









The widgets are undrawn from the screen, but the cells they occupied remain.

Getting Information

The gridInfo method returns information about the $widget in a list format. Just as with packInfo , the first two elements indicate where the widget was placed:



Here are some sample results from gridInfo <%%>



Widget Location

The gridLocation method returns the column and row of the widget nearest (x, y) coordinates:



Both $x and $y are in screen units relative to the master window (in our examples, $mw ). For locations above or to the left of the grid, -1 is returned.

When given the arguments (0, 0), our application returned this:



Propagation

There is a gridPropagate method that is similar to packPropagate <%%>



When given a false value, gridPropagate turns off geometry propagation, meaning size information is not sent upward to the parent of $master . By default, propagation is turned on. If gridPropagate is not given an argument, the current value is returned.

How Many Columns and Rows?

To find out how large the grid has become after placing numerous widgets in it, you can use gridSize to get back the number of columns and the number of rows:



The list returned contains the number of columns and then the number of rows. In many of the earlier examples, we had a grid size that was four columns by two rows.



It is not necessary for a widget to be placed in a column/row for it to be considered a valid column/row. If you place a widget specifically in column 4 and row 5 and the only other widget is in row 0 and column 0, then gridSize will return 5 and 6.

Grid Slaves

There are two ways to find out which widgets have been gridded by our $master <%%> Use gridSlaves without any arguments to get the full list or specify a row and column. Here are examples of both:





The preceding code would have printed this:



We could have specified the widget in column 0, row 0:







If you specify only the -row option, you'll get a list containing only the widgets in that row. The same goes for only specifying a -column ; your list will contain only the widgets in that column.

Place

The place() geometry manager is different than grid() or pack() . Rather than referencing against a cell location or a window's side, most of the time you'll be using a relative form of x and y coordinates with place() . You can also use place() to overlap portions of widgets, which isn't allowed in either grid() or pack() .

Invoking place() is similar to calling the other geometry managers:



The options specified when you call place() affect how the widgets are put on the screen.

Place Options

-anchor => 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | 'center'
Sets the position in the widget that will be placed at the specified coordinates.
-bordermode => 'inside' | 'outside' | 'ignore'
Determines whether or not the border portion of the widget is included in the coordinate system.
-height => amount
Sets the absolute height of the widget.
-in => $window
Indicates that the child widget will be packed inside $window instead of in the parent that created it. Any relative coordinates or sizes will still refer to the parent.
-relheight => ratio
Indicates that the height of the widget relates to the parent widget's height by ratio.
-relwidth => ratio
Indicates that the width of the widget relates to the parent widget's width by ratio.
-relx => xratio
Indicates that the widget will be placed relative to its parent by xratio
-rely => yratio
Indicates that the widget will be placed relative to its parent by yratio
-width => amount
Indicates that the width of the widget will be amount
-x => x
Indicates that the widget will be placed at x . x is any valid screen distance.
-y => y
Indicates that the widget will be placed at y . y is any valid screen distance.

Absolute Coordinates

The parent window (or frame) has a standard coordinate system where 0,0 is in the upper-left corner. The x values increase to the right, and the y values increase as you go down. See Figure 2-34 .

Figure 2-34. Coordinate system of parent window when absolute coordinates are used

To use absolute coordinates to specify where to place the widget, we would use options -x and -y <%%>



Valid values for x and y are valid screen distances (for example, "5" , which is in pixels). The widget will have its anchor position (controlled by -anchor ) placed at the x and y coordinates. The default anchor is "nw" ; the upper-left corner of the widget.

Another major difference between place() and the other geometry managers is that at least two arguments are required when place() is invoked. There are no default values for the -x and -y options . You will get an error if you try to invoke place() with no arguments (for example, $widget->place() ).

The simplest example of using -x and -y is to place a widget at 0,0:





As you would expect, the widget ends up in the upper-left corner of the window as shown in Figure 2-35 . No matter what size the window, our widget will remain positioned at (0,0). Even when the window is resized as small as possible, the widget will not move.

Figure 2-35. Button placed with -x => 0, -y => 0

Here is an example of using -x and -y to create some overlapping widgets:









Figure 2-36 shows the resulting window.

Figure 2-36. Overlapping buttons with place()

Relative Coordinates

In place() , there is an additional coordinate system defined for the parent widget that allows relative placement within it. This coordinate system is shown in Figure 2-37 .

Figure 2-37. The relative coordinate system

The upper-left corner has the coordinates (0.0,0.0). The lower-right corner's coordinates are (1.0, 1.0). The middle of the window would be (0.5, 0.5). The coordinates are specified in floating point form to allow place() to handle any size window. This allows the widget to remain at that position (in the center, for instance) no matter how the window is resized.

It is valid to specify coordinates both smaller than 0.0 and larger than 1.0. However, your widget most likely won't be completely visible in the window when you use out-of-range coordinates.

This code snippet produced the button shown in Figure 2-38 <%%>





Figure 2-38. -relx => 0.5, -rely => 0.5

Although the button in Figure 2-38 is placed in the middle of the screen, it looks off-center because the upper-left corner of the widget was placed in the middle of the window instead of the center. You can change this with the -anchor option, which I'll discuss shortly. If we resize this window, the button still stays in the middle of the window (see Figure 2-39 ).

Figure 2-39. -relx => 0.5, -rely => 0.5 window resized larger

This next example creates two buttons, both placed in the window with relative coordinates:













No matter what size the window is or where other widgets are in the screen, the two buttons will stay in those relative locations (see Figure 2-40 ).

Figure 2-40. Two buttons place relative to the parent window

The left window in Figure 2-40 is the default size of the window when it was created. The right window is what it looks like after the window was resized to make it much smaller. Notice that the second button placed in the window remains on top. It does so because we are still maintaining the ordered list of widgets in the window; the second Exit button (placed at 0.5,0.5) is drawn last, so it's drawn above the other button.

You can also combine the absolute and relative coordinate systems simply by using both in the argument list. The relative coordinate system is considered first, and then the x or y value is added to that position. The options -relx => 0.5, -x => -10 means to place the widget 10 pixels to the left of the middle of the window.

Anchoring the Widget

Think of the child widget as a piece of paper that you want to put on your bulletin board (the board is the master widget). You have a tack that you are going to use to keep the paper up on the board. You can put the tack right through the center of the paper, in the upper-left corner (nw), or in the lower-right corner (se). The point where the tack is going to stick the paper to the board is the -anchor point. The anchor point on the widget is "tacked" to the coordinates given by -x , -y or -relx , -rely . The default -anchor is "nw" Figure 2-37 shows these -anchor points within the child widget.

It is important to know where the -anchor is because it will affect how we see the widget within the master.

Figure 2-41. Different -anchor values affect where the widget is placed in the window

In Figure 2-41 , almost identical place commands were used to put the Exit button in the window, but the -anchor value was changed. The left window's button was created with this command:







The window on the right in Figure 2-41 used this command:









As with pack() and grid() , the possible values for -anchor are: 'n' , 'e' , 's' , 'w' , 'center' , 'nw' , 'sw' , 'ne' , 'se' . However, the value now applies to the child widget instead of the position within the allocation rectangle.

Width and Height

When you use place() , you can specify the width and height of the widget in one of three ways:

  • Allow the widget to determine its own size.
  • Specify width and/or height in absolute measurements.
  • Specify width and/or height in relative measurements (relative to the master widget).

To let the widgets determine their own size, no options are specified at all. The other two ways involve the options -width , -height and -relwidth , -relheight respectively.

The -width and -height options allow you to specify the exact width or height of the widget in a screen distance:



Each amount is a valid screen distance (discussed in ). The widget will be these sizes even if it cuts off edges of the items displayed in it. Our button looks quite silly on the screen when we use a -width of 40 (see Figure 2-42 ).







Figure 2-42. Using -width with place()

The other two options, -relwidth and -relheight , determine the widget in relation to the parent widget.



The ratio is a floating point number (similar to that specified by -relx or -rely ). A value of 1.0 will make the widget as wide (or as tall) as the parent widget. A value of 0.5 will make the widget half as wide as the parent (see Figure 2-43 ).

Figure 2-43. Example of same window resized with -relwidth => 0.5, -relheight => 0.5

The options -width and -relwidth are additive when used together, and so are -height and -relheight .

Border Options

Normally, the border of the widget is used as the edge of the possible space in the window, which means any widgets placed with either the absolute or relative coordinate system will be placed inside the border. This can be changed by using the -bordermode option:



Using 'outside' will allow the coordinate system to use the space occupied by the border as well. A value of 'ignore' will have the coordinate system use the space designated as the official X area. Overall, this option is pretty useless, as you can see from the difference each makes on our example in Figure 2-44 .

Figure 2-44. -bordermode examples

If you look very closely (get out your magnifying glass), you can see that the 'outside' version is two pixels higher and two pixels to the left than the 'inside' version. This is because on my window manger ( fvwm ), my border is defined as 2 pixels.

Methods Associated with Place

The methods for place() are simple and don't allow much manipulation of the widgets.

Removing the widget

As there is with pack and grid , there is a place version of the Forget method:



If you use this method on the widget, the widget will be removed from view on the screen. It is also removed from the list maintained by the parent widget.

Pack information

The placeInfo method returns a list of information related to the widget:











Place slaves


placeSlaves returns a list of the slave widgets that are within $parent . The list looks the same as it does when it is returned from packSlaves() or gridSlaves() .

Geometry Management Summary

You now know more about the three different geometry managers than you'll ever need to know to write a successful Perl/Tk application. Here are some helpful hints on deciding which geometry manger to use:

  • pack() is good for general purpose use and will be your choice around 95% of the time
  • grid() is perfect for those situations in which you would like to create a columnar layout that is similar to a spreadsheet.
  • place() is most useful when you want your widgets to stay in a position or size that is relative to the widget that created them. When it is used correctly, it can be very powerful.
  • No matter which manager you use, take the time to get the widgets on your window where they belong (or more likely, where you want them). There's nothing more unsettling than a button that looks like it just doesn't belong in the window.

As you read through this book, you'll notice that some of the option names for the geometry managers are also option names when you are creating or configuring a widget type. For example, you can specify the -width of a Button without using place() . Always keep in mind the context in which the option is used. Sometimes the functional difference is very subtle.


1. Several people have told me that pack can also take a list of widgets. I didn't cover this because it is not how pack is normally used .

2. When I used the special character "^" with Tk4.002, I got a nasty core dump. This is fixed in Tk8.0, so if you get this error also, check which version you have.

Read More Show Less

Customer Reviews

Be the first to write a review
( 0 )
Rating Distribution

5 Star

(0)

4 Star

(0)

3 Star

(0)

2 Star

(0)

1 Star

(0)

Your Rating:

Your Name: Create a Pen Name or

Barnes & Noble.com Review Rules

Our reader reviews allow you to share your comments on titles you liked, or didn't, with others. By submitting an online review, you are representing to Barnes & Noble.com that all information contained in your review is original and accurate in all respects, and that the submission of such content by you and the posting of such content by Barnes & Noble.com does not and will not violate the rights of any third party. Please follow the rules below to help ensure that your review can be posted.

Reviews by Our Customers Under the Age of 13

We highly value and respect everyone's opinion concerning the titles we offer. However, we cannot allow persons under the age of 13 to have accounts at BN.com or to post customer reviews. Please see our Terms of Use for more details.

What to exclude from your review:

Please do not write about reviews, commentary, or information posted on the product page. If you see any errors in the information on the product page, please send us an email.

Reviews should not contain any of the following:

  • - HTML tags, profanity, obscenities, vulgarities, or comments that defame anyone
  • - Time-sensitive information such as tour dates, signings, lectures, etc.
  • - Single-word reviews. Other people will read your review to discover why you liked or didn't like the title. Be descriptive.
  • - Comments focusing on the author or that may ruin the ending for others
  • - Phone numbers, addresses, URLs
  • - Pricing and availability information or alternative ordering information
  • - Advertisements or commercial solicitation

Reminder:

  • - By submitting a review, you grant to Barnes & Noble.com and its sublicensees the royalty-free, perpetual, irrevocable right and license to use the review in accordance with the Barnes & Noble.com Terms of Use.
  • - Barnes & Noble.com reserves the right not to post any review -- particularly those that do not follow the terms and conditions of these Rules. Barnes & Noble.com also reserves the right to remove any review at any time without notice.
  • - See Terms of Use for other conditions and disclaimers.
Search for Products You'd Like to Recommend

Recommend other products that relate to your review. Just search for them below and share!

Create a Pen Name

Your Pen Name is your unique identity on BN.com. It will appear on the reviews you write and other website activities. Your Pen Name cannot be edited, changed or deleted once submitted.

 
Your Pen Name can be any combination of alphanumeric characters (plus - and _), and must be at least two characters long.

Continue Anonymously
Sort by: Showing all of 2 Customer Reviews
  • Anonymous

    Posted September 19, 2002

    Good intro to Perl/Tk

    I found this book to provide enough background into the Tk module to get me started on my first Perl GUI. Between this book and the perldoc pages, I found all of my questions answered.

    Was this review helpful? Yes  No   Report this review
  • Anonymous

    Posted March 27, 2001

    Better then nothing BUT...

    The book is better then nothing but is poorly writen. The Index is also very bad,you remember reading something somewhere in the book but it takes you hours to find it again. Quite often the explanation leaves you hungry for more. There is also quite a few error in the book and when you buy a reference book you want your facts straight no guessing.

    Was this review helpful? Yes  No   Report this review
Sort by: Showing all of 2 Customer Reviews

If you find inappropriate content, please report it to Barnes & Noble
Why is this product inappropriate?
Comments (optional)