home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeMastering Perl/TkSearch this book

5.2. The Entry Widget

Until now, the only input we knew how to get from the user was a mouseclick on a Button widget (Button, Checkbutton, or Radiobutton), which is handled via the -command option. Getting input from a mouseclick is useful, but it's also limiting. The Entry widget (Figure 5-5) 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., Name, Last name, Address)

  • In a software registration 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

Figure 5-5

Figure 5-5. Entry widget

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's probably more trouble than it's worth.

The user can type anything into an Entry widget. It is up to you to decide whether 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 but get some alphabetic characters, we should issue a warning or error message to the user.

An Entry widget is much more complex 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. An Entry widget is a middle-of-the-line widget; it's more complicated than a Button, but much less complicated than the Text or Canvas widget.

5.2.1. 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.

5.2.2. Entry Options

The following list contains a short description of each option available for configuring an Entry widget. Several of the options 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
If the Boolean value specified is true, any text selected and copied 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.

-insertofftime => 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.

-invalidcommand => callback
Specifies a callback to invoke when -validatecommand returns a false result—undef disables this feature (default). Typically, just call the bell method.

-justify => 'left' | 'right' | 'center'
Sets the justification of the text in the Entry widget.

-relief => 'flat'|'groove'|'raised'|'ridge'|'sunken'|'solid'
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' | 'disabled' | 'active'
Indicates the state of the Entry.

-takefocus => 0 | 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.

-validate => validateMode
Specifies the events that invoke the -validatecommand callback: none (default), focus, focusin, focusout, key, or all.

-validatecommand => callback
Specifies a callback that validates the input; undef disables this feature (default). The callback returns false to reject the new input and invoke the -invalidcommand callback or true to accept the input.

-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 expected; we won't discuss them further: -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, "Fonts".

5.2.5. Entry Indexes

To manipulate the text in the Entry widget, you need some way to identify specific portions or positions within the text. The last example actually used an index in it. The line $e->insert('end', $_) uses the index 'end'. Just like the insert method (covered later in the chapter), all of the methods that require information about a position will ask for an index (or two, if the method requires a range of characters). This index can be as simple as 0, meaning the very beginning of the text, or something more complicated, such as 'insert'.

Here are the different forms of index specification and what they mean:

n (any integer)
A numerical character position. 0 is the first character in the string. If the Entry contains the string "My mother hit your mother right on the nose" and we use an index of 12, the character pointed to is the t in the word hit.

'insert'
The character directly following the insertion cursor. The insertion cursor is that funny-looking little bar thing that shows up inside the Entry widget when text is typed. You can move it around with the arrow keys or by clicking on a different location in the Entry widget.

'sel.first'
The first character in the selection string. This will produce an error if there is no selection. The selection string is the string created by using the mouse or Shift-arrow. The selected text is slightly raised from the background of the Entry.

If our selected text was the word nose in this string (shown here in bold):

My mother hit your mother right on the nose

'sel.first' would indicate the n.

'sel.last'
The character just after the last character in the selection string. This will also produce an error if there is no selection in the Entry widget. In the preceding example, this would mean the space after the e in nose.

'anchor'
The 'anchor' index changes depending on what has happened with the selection in the Entry widget. By default, it starts at the far left of the Entry: 0. It will change if you click anywhere in the Entry widget with the mouse. The new value will be at the index you clicked on. The 'anchor' index will also change when a new selection is made—either with the mouse (which means the 'anchor' will be wherever you clicked with the mouse) or by Shift-clicking—and 'anchor' will be set to where the selection starts. Mostly, this index is used internally, and you'll rarely find a case where it would be useful in an application.

'end'
The character just after the last one in the text string. This value is the same as if you specified the length of the entire string as an integer index.

'@x'
This form uses an x coordinate in the Entry widget. The character that contains this x coordinate will be used. "@0" indicates the leftmost (or first) character in the Entry widget. This form of index specification is also one you'll rarely use.

5.2.6. Text Selection Options

You can select the text in an Entry widget and make several things happen. The indexes 'sel.first' and 'sel.last' point to the beginning and end of the selected text, respectively. You can also make the selected text available on the clipboard on a Unix system by using the -exportselection option:

-exportselection => 0 | 1 

The -exportselection option indicates whether or not any selected text in the Entry will be put in the selection buffer in addition to being stored internal to the Entry as a selection. By leaving this option's default value, you can paste selected text into other applications.

The selected text also has some color options associated with it: -selectbackground,-selectforeground, and -selectborderwidth:

-selectbackground => color
-selectforeground => color
-selectborderwidth => amount

The -selectbackground and -selectforeground options change the color of the text and the area behind the text when that text is highlighted. In Figure 5-7, the word "text" is selected.

Figure 5-7

Figure 5-7. Entry with -selectbackground => 'red' and -selectforeground => 'yellow'

You can change the width of the edge of that selection box by using -selectborderwidth. If you left the size of the Entry widget unchanged, you wouldn't see the effects of it. The Entry widget cuts off the selection box. To actually see the results of increasing the -selectborderwidth value, use the -selectborderwidth option in the Entry command and -ipadx and -ipady in the geometry management command. Figure 5-8 illustrates -selectborderwidth.

Figure 5-8

Figure 5-8. Entry widget with -selectborderwidth => 5

You might want to change the -selectborderwidth option if you like a little extra space around your text or if you really want to emphasize the selected text. Here's the code that generated the Entry widget in Figure 5-8:

$e = $mw->Entry(-selectborderwidth => 10)->pack(-expand => 1, 
                                                -fill => 'x',
                                                -ipadx => 10,
                                                -ipady => 10);
$e->insert('end', "Select the word text in this Entry");

Notice the -ipadx and -ipady options in the pack command.

5.2.7. The Insert Cursor

The insert cursor is that funny-looking little bar that blinks on and off inside the Entry widget when it has the keyboard focus. It will only show up when the Entry widget actually has the keyboard focus. If another widget (or none) has the keyboard focus, the insertion cursor remains but is invisible. In Figure 5-9, the insertion cursor is immediately after the second "n" in the word "Insertion."

Figure 5-9

Figure 5-9. Default insertion cursor

You can change the thickness, border width, and width of the insertion cursor by using these options:

-insertbackground => color
-insertborderwidth => amount
-insertwidth => amount

The -insertwidth option changes the width of the cursor so it looks fatter. The -insertbackground option changes the overall color of the insertion cursor. Figure 5-10 shows an example.

Figure 5-10

Figure 5-10. Insertion cursor with -insertbackground => 'green' and -insertwidth => 10

No matter how wide the cursor, it is always centered over the position between two characters. The insertion cursor in Figure 5-10 is in the same location it was in Figure 5-9. This can look distracting to users and might just confuse them unnecessarily, so you most likely won't change the -insertwidth option.

You can give the insertion cursor a 3D look by using -insertborderwidth (as in Figure 5-11). Like the -insertwidth option, the -insertborderwidth option doesn't have much practical use.

Figure 5-11

Figure 5-11. -insertborderwidth => 5, -insertbackground => 'green', and -insertwidth => 10

You can change the amount of time the cursor blinks on and off by using these options:

-insertofftime => time
-insertontime => time

The default value for -insertofftime is 300 milliseconds. The default for -insertontime is 600 milliseconds. The default values make the cursor's blink stay on twice as long as it is off. Any value specified for these options must be nonnegative.

For a really frantic-looking cursor, change both values to something much smaller. For a relaxed and mellow cursor, double the default times. If you don't like a blinking cursor, change -insertofftime to 0.

5.2.9. Entry Widget Validation

You can perform input validation as characters are typed in an Entry widget, although, by default, validation is disabled. You enable validation using the -validate option, specifiying what events trigger your validation subroutine. The possible values for this option are focus and focusin (when the Entry gets the keyboard focus), focusout (when the Entry loses focus), key (on any key press), or all.

The -validatecommand callback should return true to accept the input or false to reject it. When false is returned, the -invalidcommand callback is executed.

The -validatecommand and -invalidcommand callbacks are called with these arguments:

  • The proposed value of the Entry (the value of the text variable too)

  • The characters to be added or deleted; undef if called due to focus, explicit call, or change in text variable

  • The current value before the proposed change

  • The index of the string to be added/deleted, if any; otherwise, -1

  • The type of action: 1 for insert, 0 for delete, -1 if a forced validation or text variable validation

This Entry ensures that characters are restricted to those in the string "perl/Tk", without regard to case:

my $e = $mw->Entry(
    -validate        => 'key',
    -validatecommand => sub {$_[1] =~ /[perl\/Tk]/i},
    -invalidcommand  => sub {$mw->bell},
)->pack;

5.2.10. Using a Scrollbar

If the information requested from the user could get lengthy, the user can use the arrow keys to manually scroll through the text. To make it easier, we can create and assign a horizontal Scrollbar to the Entry widget by using the -xscrollcommand option:

-xscrollcommand => [ 'set' => $scrollbar ]

For now, we're going to show you the most basic way to assign a Scrollbar to the Entry widget. For more details on the Scrollbar, see Chapter 6, "The Scrollbar Widget".

The following code creates a Scrollbar and associates it with an Entry widget:

$scroll = $mw->Scrollbar(-orient => "horizontal"); # create Scrollbar
$e = $mw->Entry(-xscrollcommand => [ 'set' => $scroll ])->
  pack(-expand => 1, -fill => 'x'); # create Entry
$scroll->pack(-expand => 1, -fill => 'x');
$scroll->configure(-command => [ $e => 'xview' ]); # link them
$e->insert('end', "Really really really long text string");

Figure 5-13 shows the resulting window in two states: on the left, the window as it looked when it was created, and on the right, how it looks after scrolling all the way to the right.

Figure 5-13

Figure 5-13. Scrollbar and an Entry widget

You'll rarely want to use a Scrollbar with an Entry widget. The Scrollbar doubles the amount of space taken, and you can get the same functionality without it by simply using the arrow keys when the Entry widget has the focus. If the user needs to enter multiple lines of text, you should use a Text widget instead. See Chapter 8, "The Text, TextUndo,and ROText Widgets" for more information on what a Text widget can do.

5.2.12. Deleting Text

You can use the delete method when you want to remove some or all of the text from the Entry widget. You can specify a range of indexes to remove two or more characters or a single index to remove one character:

$entry->delete(firstindex, [ lastindex ])

To remove all the text, you can use $entry->delete(0, 'end'). If you use the -textvariable option, you can also delete the contents by reassigning the variable to an empty string: $variable = "".

Here are some other examples of how to use the delete method:

$entry->delete(0);        # Remove only the first character
$entry->delete(1);        # Remove the second character

$entry->delete('sel.first', 'sel.last')  # Remove selected text
   if $entry->selectionPresent();        # if present

5.2.17. Scanning Text

Both scanMark and scanDragto allow fast scrolling within the Entry widget. A call to scanMark simply records the x coordinate passed in for use later with scanDragto. It returns an empty string.

$entry->scanMark(x);
$entry->scanDragto(x);

The companion function to scanMark is scanDragto, which also takes an x coordinate. The new coordinate is compared to the scanMark x coordinate. The view within the Entry widget is adjusted by 10 times the difference between the coordinates.

And don't forget you can always drag the contents of the Entry widget left and right by holding down mouse button 2.

5.2.18. Working with the Selection

The selection method has several possible argument lists. If you look at the web page documentation, you'll see that you can use:

$entry->selectionAdjust(index). 

You might also see the form $entry->selection('adjust', index), where 'adjust' is the first argument. Be aware that they mean the same thing as you read code written by other people.

You can adjust the selection to a specified index by using selectionAdjust:

$entry->selectionAdjust(index);

The selected text is extended toward the index (from whichever end is closest).

To clear out the selection:

$entry->selectionClear( );

Any selection indicator is removed from the Entry widget, and the indexes 'sel.first' and 'sel.last' are now undefined. The selected text remains.

To reset the 'anchor' index to the specified index, use selectionFrom:

$entry->selectionFrom(index);

This does not affect any currently selected text or the indexes 'sel.first' and 'sel.last'.

The only way to check if there is a selection in the Entry widget is to use selectionPresent:

if ($entry->selectionPresent( )) {
}

It returns a 1 if there is a selection, which means you can safely use the 'sel.first' and 'sel.last' indexes (if there isn't a selection, an error will be printed when you refer to either index). selectionPresent will return a 0 if there is no current selection.

You can change the selection range by calling selectionRange:

$entry->selectionRange(startindex, endindex);

The two indexes indicate where you would like the selection to cover. If startindex is the same or greater than endindex, the selection is cleared, causing 'sel.first' and 'sel.last' to be undefined. Otherwise, 'sel.first' and 'sel.last' are defined the same as startindex and endindex, respectively.

The selectionTo method causes the new selection to be set from the current 'anchor' point to the specified index:

$entry->selectionTo(index);


Library Navigation Links

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