Navigation Logo 11.4  Enhancing Caps with Tab Navigation Logo

 

 

In this section, the Caps script is changed so that the .edit_button button performs not one but two functions. The Tab key is used to switch between the functions. This alters the Tab key from its default behavior.

The default behavior of the Tab key is to switch the focus between those widgets which are capable of taking the focus. There is no real need to switch the focus in the Caps example. Although the button widgets can take the focus – they show they have the focus by getting a black border – it is not normally used when a mouse is available.

This enhancement of the Caps example forces us to look at the bind command. The bind command is needed to associate our own event handler with the use of the Tab key.

The string .edit_button names a button widget and a widget command. All widget commands, that is to say all widget object action families, have a configure action that can be used to change the option values. This action can be applied to almost any option that can be set when the widget is created. Here is the way to change the .edit_button's -text and -command options.

.edit_button configure -text Small \
             -command { set Entry [string tolower $Entry] }
As you can see, the button's label is changed to "Small" and the associated event handler is changed to a script that will convert all the letters in Entry to lowercase.

A similar use of the .edit_button widget command can change the .edit_button button back to its original configuration.

Procedures for Switching the Edit Button's State

The revised script needs a way to know which .edit_button configure action to execute. There are various ways to accomplish this. The one used is to keep a top-level variable, switchState, whose value is the name of the procedure to execute the next time the .edit_button widget is to be reconfigured. Part of what that procedure must do is change the value of switchState.

Remark

You may have noticed that switchState is not quite consistent with my usual practice of starting variable names with uppercase letters and procedure names with lowercase letters. This is because the variable switchState exists to name a procedure.

The two procedures for switching .edit_button configuration are initForCaps and initForSmall. You can see them in Figure 11.4a.

One difference between the root window shown in Figure 11.1b (The Caps example) and the root window shown in Figure 11.4a (The enhanced Caps example) has nothing to do with the changes to the script. The entry area in Figure 11.4a has a black border and shows a cursor. That is not true in Figure 11.1b. The reason is that no focus is apparent in Figure 11.1b whereas in Figure 11.4a, the entry widget has the focus.

Figure 11.4a: The enhanced caps example.
proc initForCaps {} {

global switchState

.edit_button configure -text Caps \

-command { set Entry [string toupper $Entry] }

set switchState initForSmall } proc initForSmall {} {

global switchState

.edit_button configure -text Small \

-command { set Entry [string tolower $Entry] }

set switchState initForCaps } proc quit {} {

global Entry switchState

destroy .entry .edit_button .quit_button

unset Entry switchState

bind . <Key-Tab> {} } entry .entry -textvariable Entry pack .entry button .edit_button pack .edit_button button .quit_button -text Quit -command { quit } pack .quit_button initForCaps bind . <Key-Tab> { $switchState; break }

All that remains to explain the revised script is to describe how bind is used.

The Bind Command

If you can accomplish what you need through Tk's widgets you should do so. It is likely that your code will be less portable and have more errors when you use the bind command. Still, there are times when the bind command is very helpful.

What bind does is arrange for an event handler to be triggered by a particular kind of event involving some set of widgets. Usually the event is a user event. Samples are:

<Key-Tab>
<Control-key-a>
Event handlers are the same kind of scripts passed as values to the -command option. Windows can be identified with their names.

Returning to the enhanced Caps example, here is a command line that binds a switch of states to the Tab key.

bind all <Key-Tab> { $switchState; break }
The binding is effective when any widget in the application has the focus.

If you wanted to bind the exit action to the user event of a user pressing the letter "c" with the control (or Ctl) key held down, you might do it this way:

bind all <Control-Key-c> exit
But, if for some reason you wanted the binding only to apply over a button widget named .quit_button, you would write
 
bind .quit_button <Control-Key-c> exit

Because bindings may apply to many widgets, any one widget may be involved with several bindings to the same event. The order in which these bindings fire is important. For one reason, if there is a break command in an event handler, then any other bindings to the same event which may be ready to fire will be ignored. Sorting out what happens in such circumstances is complicated and the discussion is left until Bindings below. For now, here is an exercise to get you started thinking about what is going on.

Exercise 11.4a

Add the following commands to Script S11.1a.
 
bind .quit_button <Motion> { break }
bind . <Motion> { puts {That tickles!}}
Because of the use of puts, this script needs to be executed interactively. Describe the effect.

Solution

Exercise 11.4b

Start the wish?? interpreter and type some bindings of control keys to simple event handlers directly into the command window. Immediately after you have executed a bind command you can test the effect in the root window.

One possible event handler for this test is

{ puts "Lookatthat"; break }
though with the empty root window you will not need the break. The puts command does the same thing it does in Tcl – it prints in the command window.

Solution

When you assign an empty string as the event handler to a binding, you are clearing that binding. For the enhanced Caps example this is done in the quit procedure where you will find this line:

bind . <Key-Tab> {}

Putting It Together

The complete enhanced Caps example is shown in Figure 11.4a. Pretty much everything has been explained. The default values for -text and -command are not changed when the .edit_button widget is created. This is pure laziness. They do not need to be set at widget creation time because they are set by the initForCaps command line that also initializes the switchState variable.

Exercise 11.4c

What would be the effect of moving the initForCaps command line to just before the entry ... command line? Explain.

Solution

Exercise 11.4d

What would be the effect of moving the last command line to the beginning of the script? Explain.

Solution

 

 

[Sample TK Application]
Author's Home Page
Navigation Logo [Book's Cover]
Order from Amazon.