The way that bindings are handled with a TkTable is the same as with all built-in Tk widgets. By default, when a widget receives an event, it fires bindings matching the event that are installed in any of the following locations (referred to as
binding tags):[ol][li]On the widget itself (for example, ".t"

[/li][li]On the widget's class (for example, "Text" for a text widget)[/li][li]On the toplevel window containing the widget (for example, "."

[/li][li]On a symbolic binding tag named "all"[/li][/ol]By default, Tcl examines those binding tags in the order listed above, and at each step executes any matching binding. Thus, a single event on a widget could trigger 4 separate binding actions, one from each binding tag. So as you can see, the default behavior if you were to create your own bindings on a TkTable widget would be for Tcl to execute your matching binding before the built-in TkTable matching binding. (The built-in TkTable bindings are implemented in the "Table" widget class bindtag.)
The reason for including the toplevel window in the list of a widget's binding tags isn't immediately obvious to most people. But it allows you to create keyboard shortcuts that are in effect for the entire window (but only that window). For example, If you wanted the key sequence Ctrl+t to open up a secondary window, you could do the following:
Code:
bind . <Control-KeyPress-t> {
openSubwindow
}
and the binding would be active everywhere within your main window. On the other hand, if you want the key sequence Ctrl+q to quit your application, no matter which window you're in, you'd bind to the "all" bindtag:
Code:
bind all <Control-KeyPress-q> {
exit
}
Tcl, being the flexible beast that it is, allows you to modify this behavior. One way is by including a
break command in a binding action. This stops the propagation of the event to subsequent binding tags. For example, we could create a binding on an entry widget that allows the user to insert a tab character. (Usually, the tab key is ignored by an entry widget, and bindings in "all" then manage transfering keyboard focus to the next widget that can receive focus.) If the text widget in question is named ".e", you could do this:
Code:
bind .e <KeyPress-Tab> {
.e insert insert "\t"
break
}
But sometimes, you'd like both your binding and the built-in binding to fire, but you want the widget class binding to execute first.
In this case, you'll need to use another Tcl command called
bindtags, which actually changes the order in which the widget's binding tags are examined. If you execute
bindtags with only a widget name as an argument, it returns a list of the current binding tags. For example:
[tt]%
bindtags .t
.t Text . all[/tt]
We can change the binding tags for a widget by providing a new list as a second argument to the
bindtags command. For example, the following command causes our text widget, .t, to look for bindings in the Text class first, followed by bindings on the widget, then the toplevel window, and finally "all":
Code:
bindtags .t [list Text .t . all]
In general, the
bindtags command is a very powerful tool. In conjunction with the
bind command, it allows you to create new, symbolic binding tags that you can insert in the binding path of any widget. This is a great technique for implementing "modes" in your application, or creating sets of bindings that you can install easily on collections of widgets. To do so, create your bindings on a new symbolic binding tag. Then use
bindtags to install the set of bindings on any widget you like. For example:
Code:
bind highlight <Enter> {
# When the mouse enters a widget,
# highlight it by changing its
# background color to red.
# Save the old background color
set oldbg [%W cget -bg]
%W configure -bg red
}
bind highlight <Leave> {
# "Unhighlight" a widget by restoring
# its original bacground color
%W configure -bg $oldbg
}
# Insert the new bindtag into the path
# of whatever widgets we like
bindtags .ok [concat highlight [bindtags .ok]]
bindtags .cancel [concat highlight [bindtags .cancel]]
- Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax