I'm assuming that
japskar is employing a rather common Tcl technique of binding the KeyPresses he mentioned to the toplevel window, for example:
Code:
button .ok -text "Ok" -command {
puts "You clicked: Ok"
}
button .cancel -text Cancel -command {
puts "You clicked: Cancel"
}
pack .ok .cancel -pady 2
bind . <KeyPress-Return> {
.ok flash
.ok invoke
}
bind . <KeyPress-Escape> {
.cancel flash
.cancel invoke
}
This causes these keyboard "shortcuts" to be active in the entire window, no matter which widget has keyboard focus. It works because of the way events are handled in Tcl. 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.
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. This might lead you to believe that we've found the solution to
japskar's problem. If the text widget in question is named ".t", you might try this:
Code:
bind .t <KeyPress-Return> {
break
}
Unfortunately, this breaks our text widget because much of a text widget's behavior is controled by bindings installed in the Text class binding tag. By suppressing the propagation of the <KeyPress-Return> event to the Text binding tag, we don't fire the binding that actually inserts the "\n" into the text widget.
In this case, a better solution is to use another Tcl command called
bindtags to actually change 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]
Now, if we have the binding on .t that executes
break in response to a <KeyPress-Return> event, everything works fine. The Text class bindings fire first, inserting the "\n" into the widget. Then, the .t binding fires, which executes
break and stops the further propagation of the event.
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