Book HomeMastering Perl/TkSearch this book

Chapter 5. Label and Entry Widgets

Contents:

The Label Widget
The Entry Widget
The Perl/Tk LabEntry Mega-Widget

There are times you'll want users to type in specific information, such as their names, addresses, or even serial numbers. The simplest way to do this is to use Entry widgets. You can use a Label widget with an Entry to clearly communicate to the user what should be typed in the Entry. Most often, you'll see the Label and Entry combination used multiple times in a database Entry-type window where there are many different pieces of information the user must enter.

5.1. The Label Widget

A Label is like a Button that doesn't do anything. It is a noninteractive widget and by default cannot have the keyboard focus (meaning you can't tab to it). It does nothing when you click on it (see Figure 5-1).

Figure 5-1

Figure 5-1. Label widget

Excluding Frame-like widgets, the Label is the simplest widget. It is similar to a Button in that it can show text (or a bitmap), have relief (default is flat), display multiple lines of text, have a different font, and so on. Figure 5-2 shows a simple window, with both a Button and Label, created with this code:

use Tk;
$mw = MainWindow->new( );
$mw->Label(-text => "Label Widget")->pack( );
$mw->Button(-text => "Exit", -command => sub { exit })->pack( );
MainLoop;
Figure 5-2

Figure 5-2. A simple window with Label and Button

Here are some typical uses for a Label:

5.1.1. Creating a Label

The command to create a Label is, of course, Label. Here's the basic usage:

$label = $parent->Label( [ option => value . . . ] )->pack( );

Hopefully you are starting to see a trend in the creation command. As you might expect, when you create a Label, you can specify options that will change its appearance and how it behaves.

5.1.2. Label Options

The following is a comprehensive list of options for Labels:

-anchor => 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | 'center'
Causes the text to stick to that position in the Label widget. This won't be obvious unless the Label is forced to be larger than standard size.

-background => color
Sets the background color of the Label to color.

-bitmap => bitmap
Displays the bitmap contained in bitmap instead of text.

-borderwidth => amount
Changes the width of the edges of the Label.

-cursor => cursorname
Changes the cursor to cursorname when the mouse is over this widget.

-font => fontname
Indicates that the text in the widget will be displayed with fontname.

-foreground => color
Changes the text of the Button (or the bitmap) to color.

-height => amount
Sets the height of the Label to amount; amount is a valid screen distance.

-highlightbackground => color
Sets the color of the focus rectangle when the widget is not in focus to color.

-highlightcolor => color
Sets the color of the focus rectangle when the widget has focus to color.

-highlightthickness => amount
Sets the width of the focus rectangle. Default is 0 for the Label.

-image => imgptr
Displays the image to which imgptr points, instead of text.

-justify => 'left' | 'right' | 'center'
Sets the side of the Label against which multiline text will justify.

-padx => amount
Adds extra space inside the edge to the left and right of the Label.

-pady => amount
Adds extra space inside the edge to the top and bottom of the Label.

-relief => 'flat' | 'groove' | 'raised' | 'ridge' | 'sunken'
Changes the type of edges drawn around the Button.

-takefocus => 0 | 1 | undef
Changes the ability of the Label to have the focus or not.

-text => text
Displays a text string in the Label.

-textvariable => \$variable
Points to the variable containing text to be displayed in the Label. Label will change automatically as $variable changes.

-underline => n
Causes the nth character to be underlined. Allows that key to invoke the widget when it has the focus. Default value is -1 (no character underlined).

-width => amount
Causes the Label width to be amount.

-wraplength => amount
Indicates that the text in the Label will wrap when it gets longer than amount.

This list briefly describes each option and what it does. Some of the options have different defaults for the Label widget than we are used to seeing with Button-type widgets, causing the Label to behave a bit differently.

5.1.3. How a Label Differs from Other Widgets

When we created Button-type widgets, we could either click them with the mouse or tab to them and then use the keyboard to press the Button. A Label widget, on the other hand, does not interact with the user unless we add explicit bindings. It is there for informational purposes only, so there is no -command option.

The default value for the -takefocus option is 0, which means you cannot tab to it. When tabbing between widgets on the screen, the highlight rectangle shows us which widget currently has the keyboard focus. Since we don't allow the Label to have the focus (remember, -takefocus is set to 0), it doesn't make sense to have a visible highlight rectangle. The default value for the -highlightthickness option in a Label widget is 0. You can make a rectangle appear around a Label by setting -highlightthickness to something greater than 0, and setting -highlightbackground to a color, such as blue or red.

The Label widget also doesn't have a -state option. Since we shouldn't be able to click a Label, we should never have to disable it.

5.1.4. Relief

In Figure 5-3, you can see what happens when you change the Label's -relief option. Notice that the edges of the widget are very close to the text. Unlike a Button, you usually don't want much extra space around the Label (space is controlled by the -padx and -pady options). Normally you want the Label widget to sit right next to the widget (or widgets) it is describing.

Figure 5-3

Figure 5-3. Labels with different relief values; window on right has a -borderwidth of 10

Seeing what a widget looks like with different relief values sometimes helps determine where the widget ends, especially with a widget that has a default value of 'flat'. Also, changing the relief of different widgets ensures that we know which widgets are where on the screen. After creating 10 Entries and Labels with less-than-creative variable names, it's easy to lose track. Changing the border width is bound to make that one widget stand out. Color is also a good way to make a diagnostic message.

5.1.5. Status Message Example

You can use the groove or ridge relief when making a help or status Label along the bottom of a window. Such a Label is packed with -side => 'bottom' and -fill => 'x'. There are two different ways you can use a status Label:

Both types are demonstrated in the following sample code.

This code shows the "What I'm doing now" type of help Label:

$mw->Label(-textvariable => \$message, -borderwidth => 2, 
           -relief => 'groove')->pack(-fill => 'x', 
                                      -side => 'bottom');
$mw->Text( )->pack(-side => 'top', 
                            -expand => 1, 
                            -fill => 'both');

$message = "Loading file index.html...";
...
$message = "Done";

The Label is created across the bottom of the screen. We pack it first because we want it to stay on the screen if we resize the window (remember, the last widgets packed get lower priority if the window runs out of room). As the program executes (represented by the ...), it changes the Label accordingly.

This code shows an example of using a widget-helper help Label:

$mw->title("Help Label Example");

$mw->Label(-textvariable => \$message)
   ->pack(-side => 'bottom', -fill => 'x');

$b = $mw->Button(-text => "Exit", -command => \&exit, -relief => 'groove')
        ->pack(-side => 'left');
&bind_message($b, "Press to quit the application");

$b2 = $mw->Button(-text => "Do Nothing")->pack(-side => 'left');
&bind_message($b2, "This Button does absolutely nothing!");

$b3 = $mw->Button(-text => "Something", 
  -command => sub { print "something\n"; })->pack(-side => 'left');
&bind_message($b3, "Prints the text 'something'");

sub bind_message {
  my ($widget, $msg) = @_;
  $widget->bind('<Enter>', [ sub { $message = $_[1]; }, $msg ]);
  $widget->bind('<Leave>', sub { $message = ""; });
}

This example is a bit longer, because we are using the bind method (the bind method is explained in more detail in Chapter 15, "Anatomy of the MainLoop"). We want to associate a help message with each widget we create. We do this by adding bindings to each widget, which change the variable $message to a specified string when the mouse enters the widget and to an empty string if the mouse leaves the widget. We use a subroutine to avoid writing the same two bind lines over and over. Figure 5-4 shows what our window looks like with the mouse over the center Button.

Figure 5-4

Figure 5-4. Window with Label across the bottom

5.1.6. Container Frames

In Figure 5-4, you can see the example text is centered within the Label widget. When using a single line Label and filling the widget across the screen, the text remains centered, even if you add the-justify => 'left' option. You can get around this by creating a container Frame, giving it the desired relief, filling the Frame across the screen (instead of the Label), and placing the Label widget within the Frame:

$f = $mw->Frame(-relief => 'groove',
                -bd => 2)->pack(-side => 'bottom',
                                -fill => 'x');
$f->Label(-textvariable => \$message,)->pack(-side => 'left');

This allows the Label to grow and shrink within the Frame as necessary, while the text sticks to the left side. Even better, perhaps, is to simply use -anchor => 'w' when configuring the Label.

If you've typed in this short example and played with the strings bound to each widget, you might have noticed that the window will resize itself if the text assigned to $message is too long to display in the Label. This can get annoying if your window is fairly small to begin with. There are two ways to deal with this: first, you can always use really short text strings; second, you can tell the window not to resize when the Label changes size.

The drawbacks with each approach aren't too bad, and which one you pick just depends on the application you are working on. If you can write really short sentences that make sense, great. Telling the window not to resize is almost as easy, though; it is accomplished by adding one line to your program:

$mw->packPropagate(0);

Using packPropagate will cause your window not to resize when a widget is placed inside the window (we first talked about packPropagate in Chapter 2, "Geometry Management"). This means that your window might not show all your widgets right away. You can deal with this by keeping packPropagate on until you get all your widgets in, figuring out a good starting size for your window, and using $mw->geometry(size) to request that size initially. (See Chapter 11, "Frame, MainWindow,and Toplevel Widgets" for info on the geometry method.)

5.1.7. 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 Chapter 5, "Label and Entry Widgets" for details on arguments and return values.



Library Navigation Links

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