Tcl/Tk: can't bind to Escape and Return
I can't bind
the Escape
and Return
keys in my Tcl/Tk code. The following code reproduces the bug. When I hit Esc
or Enter
key I get the following error message:
Error: can't read "cmd": no such variable
proc OkCancel { cmd } {
button .${cmd}.ok -text "OK" -command [list myOk $cmd ]
button .${cmd}.cancel -text "Cancel" -command [list myCancel .$cmd]
grid .${cmd}.ok .${cmd}.cancel -sticky e
bind .$cmd <Return> { myOk $cmd ; break }
bind .$cmd <Escape> { myCancel .${cmd} ; break }
}
proc myOk { cmd } {
puts "The command name is = $cmd"
}
proc myCancel {开发者_如何学编程 arg } {
destroy $arg
}
proc test { } {
set cmd "hello"
toplevel .$cmd
OkCancel $cmd
}
test
That's because when an event fires, the script bound to it gets eval
uated at the global level (as per the bind
manual). That is, in case of your <Return>
binding, the script myOk $cmd ; break
will be executed, literally. Hence, if there exists no variable named "cmd" in the global namespace at the time your script runs, the error you have shown will be triggered.
To fix the problem, there are several ways:
- Make the
$cmd
substitution be evaluated at the time the script is created and bound. To do this, just replace {} with "" to allow variable substitution, that is, if you'd writebind .$cmd <Return> " myOk $cmd ; break "
the bound script would bemyOK hello ; break
- Turn the callback script into a procedure call and pass it explicit parameters, like this:
bind .$cmd <Return> [list mycallback $cmd]
and then make sure you have definedmycallback
procedure accepting one parameter. This way you can write generic event handlers which are parameterized by whatever parameters you need at the time of the binding. - Use
namespace code
or a similar tool to make your script executed in a specified namespace which has the specified variable defined.
In all cases beware that since your $cmd may in certain cases expand to something odd, it's a good idea to protect the whole script from such a situation--that's what [list ...]
does in the second example (see this for more info).
精彩评论