Book HomeMastering Perl/TkSearch this book

8.17. Embedding Widgets

One of the best things you can do with a Text widget is put other widgets (such as Button or Entry widgets) inside it. One advantage of embedding widgets is you can create a scrolled set of widgets on a line-by-line basis.

Before we go over all the different functions available to work with embedded widgets, let's look at a quick example. We often want to do a lot of data entry in a program, which means we need a lot of Label and Entry widgets. Sometimes there are so many of them that it's hard to fit them all on the screen without making a mess of the window. By using a scrolled Text widget and putting the Label and Entry widgets inside it, we can create a lot more widgets in a smaller space. Here's the code:

use Tk;

$mw = MainWindow->new;
$mw->title("Data Entry");
$f = $mw->Frame->pack(-side => 'bottom');
$f->Button(-text => "Exit", 
           -command => sub { exit; })->pack(-side => 'left');
$f->Button(-text => "Save",
           -command => sub {  # do something with %info; 
		   })->pack(-side => 'bottom');
$t = $mw->Scrolled("Text", -width => 40, 
                   -wrap => 'none')->pack(-expand => 1, -fill => 'both');

foreach (qw/Name Address City State Zip Phone Occupation 
            Company Business_Address Business_Phone/) {
		$w = $t->Label(-text => "$_:", -relief => 'groove', -width => 20);
		$t->windowCreate('end', -window => $w);
		$w = $t->Entry(-width => 20, -textvariable => \$info{$_});
		$t->windowCreate('end', -window => $w);
		$t->insert('end', "\n");
}
$t->configure(-state => 'disabled'); # disallows user typing

MainLoop;

Figure 8-6 shows the Win32 version of this window.

Figure 8-6

Figure 8-6. Text widget containing other widgets

We disable the Text widget before running MainLoop because we don't want the user to be able to type text directly into the Text widget. This only disables the ability to enter or delete text; the internal widgets still function normally. We also turn off the -wrap option so the Label and Entry widgets don't accidentally drop down to the next line when the window is resized.

You could put a Text widget inside another Text widget, but you probably wouldn't want to.

8.17.1. windowCreate, windowCget, and windowConfigure

As you can see from the preceding example, we use the windowCreate method to insert an embedded widget. The widget should have been created already, and it should be a child of the Text widget. The general syntax is:

$widget = $text->Widget( ... );
$text->windowCreate(index, -window => $widget,[option => value ] );

In the previous example, we used the 'end' index. You can use any valid Text widget index to insert the embedded widgets. The only option we used was a -window option with the reference to the new $widget.

Here are the available options for the windowCreate method:

-align => [ 'baseline' | 'bottom' | 'center' | 'top' ]
Determines where the widget is placed within the line if it is not as tall as the line itself.

-padx => amount
-pady => amount
Adds space around the widget in the x and y directions, respectively (-padx => 10).

-stretch => 0 | 1
Takes a Boolean value (1 or 0). A true value will stretch the widgets to fill the line from top to bottom.

-window => $widget
Takes a reference to another widget.

There are several different forms of the window method. The first one, the "Create" form, creates the widget within the Text widget. The "Names" form lets you know what types of widgets are embedded in the Text widget:

@types = $text->windowNames( );

The results use the format of the Tcl widget hierarchy (see Chapter 13, "Miscellaneous Perl/Tk Methods"):

.text.radiobutton .text.label .text.button .text.entry .text.checkbutton

Use the windowCget method to get information about the options used when the window was created in the Text widget:

$value = $text->windowCget(index, option);

To use windowCget, you need to know the index the widget is currently occupying (each widget occupies one character in the Text widget, even if it looks like it takes more space).

windowConfigure allows us to change the options associated with the widget at index or retrieve the value of the configuration option:

$text->windowConfigure(index [, option => value ] );

Remember that the only options you can use with this method are -align, -padx, -pady, -stretch, and -window. Other than this, windowConfigure(...) behaves just like a regular widget's configure method. To make changes on the $widget directly, use $widget->configure(...).



Library Navigation Links

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