[ Team LiB ] Previous Section Next Section

Using Entry Widgets

The entry widget supports editing, scrolling, and selections, which make it more complex than label or message widgets. Fortunately, the default settings for an entry widget make it usable right away. You click with the left button to set the insert point and then type in text. Text is selected by dragging out a selection with the left button. The entry can be scrolled horizontally by dragging with the middle mouse button.

One common use of an entry widget is to associate a label with it, and a command to execute when <Return> is pressed in the entry. The grid geometry manager is ideal for lining up several entries and their labels. This is implemented in the following example:

Example 34-1 Associating entry widgets with variables and commands

graphics/34inf01.gif

foreach {field label} {name Name address1 Address
          address2 {} phone Phone} {
   label .l$field -text $label -anchor w
   entry .e$field -textvariable address($field) -relief sunken
   grid .l$field .e$field -sticky news
   bind .e$field <Return> UpdateAddress
}

Example 34-1 creates four entries that are linked to variables with the textvariable attribute. The variables are elements of the address array. The -relief sunken for the entry widget sets them apart visually. Widget relief is described in more detail on page 614. The Tcl command UpdateAddress is bound to the <Return> keystroke. The UpdateAddress procedure, which is not shown, can get the current values of the entry widgets through the global array address.

Validating Entry Contents

As of Tk 8.3, entry widgets gained several new options that make it easy to prevent users from entering invalid text into an entry.

The validate attribute determines when validation should take place. A value of none (the default) disables validation. Other supported values are: focusin (receiving keyboard focus), focusout (losing focus), focus (gaining or losing focus), key (any keypress), and all.

For validation to take effect, you must also provide a value for the validateCommand (or -vcmd) attribute. This is a Tcl script to execute whenever validation takes place. If the script returns a Boolean True, the proposed change to the widget is accepted; if the script returns a Boolean False, the proposed change is rejected and the widget's text remains the same.

Optionally, you can also assign a Tcl script to the invalidCommand attribute. This script executes if the validation script returns False.

The validateCommand validation script can contain "percent substitutions," just like in an event binding. These substitutions occur before executing the script, whenever validation is triggered. Table 34-1 lists the validation substitutions:

Table 34-1. Entry and spinbox validation substitutions

%d

The type of action that triggered validation: 1 for insert; 0 for delete; -1 for focus, forced or textvariable validation.

%i

Index of the character string to be inserted or deleted, if any; otherwise -1.

%P

The value of the widget should the change occur.

%s

The current value before the proposed change.

%v

The type of validation currently set (that is, the current value of the validate attribute).

%V

The type of validation that triggered the callback: key, focusin, focusout, forced.

%W

The name of the widget that triggered the validation.

Example 34-2 demonstrates using validation to allow a user to enter only integer values into an entry.

Example 34-2 Restricting entry text to integer values

graphics/34inf02.gif

proc ValidInt {val} {
   return [ expr {[string is integer $val]
      || [string match {[-+]} $val]} ]
}

entry .e -validate all -vcmd {ValidInt %P}
pack .e

graphics/common_icon.gif

Validation errors turn off validation.


If an uncaught error occurs during the validation callback, then the validate attribute is set to none, preventing further validation from taking place. Additionally, if the return value of the validation callback is anything other than a Boolean value, validation is also disabled. Therefore, you should take care not to raise errors or return non-Boolean values from your validation callback.

graphics/common_icon.gif

Be careful with textvariables and validation.


Using textvariables for read-only purposes never causes a problem. However, you can run into trouble if you try to change the value of an entry using its textvariable. If you set the textvariable to a value that wouldn't be accepted by the validation script (that is, it would return False), then Tk allows the change to occur, but disables further validation by setting validate to none. So in general, you should use textvariables only to read an entry's value if you also have validation enabled.

graphics/common_icon.gif

Changing a widget's value during validation disables future validation.


The other caveat to validation is that if you change the value of the widget while evaluating either the validation script or the invalidCommand script, validate is set to none, disabling further validations. The intent is to prevent the change from triggering yet another validation check, which could attempt to change the widget and trigger another validation, and so on in an endless cycle.

For most validation applications, this is not a major restriction. In most cases, you simply want to prevent an invalid change from taking place, which you accomplish simply by returning Boolean False from your validation script.

But some sophisticated validation schemes might require edits to the widget's text. If you need to change the value of the entry from either the validateCommand or invalidCommand script, the script should also schedule an idle task to reset the validate attribute back to its previous value. Example demonstrates this with a validation command that ensures all letters inserted into an entry are upper case, by converting all characters to upper case as they are inserted. As this example modifies the value of the widget directly, it must reestablish validation in an idle task.

Example 34-3 Reestablishing validation using an idle task
proc Upper {w validation action new} {
   if {$action == 1} {
      $w insert insert [string toupper $new]
      after idle [list $w configure -validate $validation]
   }
   return 1
}

entry .e -validate all -vcmd {Upper %W %v %d %S}
pack .e

Tips for Using Entry Widgets

graphics/common_icon.gif

If you are displaying long strings in an entry, you can use the following command to keep the end of the string in view. The command requests that all the string be off screen to the left, but the widget implementation fills up the display; the scrolling is limited so that the tail of the string is visible:

$entry xview moveto 1.0

The show attribute is useful for entries that accept passwords or other sensitive information. If show is not empty, it is used as the character to display instead of the real value:

$entry config -show *

The state attribute determines if the contents of an entry can be modified. Set the state to disabled to prevent modification and set it to normal to allow modification.

$entry config -state disabled ;# read-only
$entry config -state normal   ;# editable

Tcl 8.4 added a new state, readonly, in which the contents of the widget can't be edited, just like disabled. However, the readonly state allows the user to select and copy the widget contents. If the widget is a spinbox, the user can also use the up and down spinbuttons to change the value displayed while the widget is in readonly state (but not if it is in the disabled state).

The middle mouse button (<Button-2>) is overloaded with two functions. If you click and release the middle button, the selection is inserted at the insert cursor. The location of the middle click does not matter. If you press and hold the middle button, you can scroll the contents of the entry by dragging the mouse to the left or right.

    [ Team LiB ] Previous Section Next Section