Tcl/Tk:无法绑定到 Escape 和 Return
我无法在 Tcl/Tk 代码中绑定
Escape
和 Return
键。以下代码重现了该错误。当我按 Esc
或 Enter
键时,我收到以下错误消息:
错误:无法读取“cmd”:没有这样的变量
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为当事件触发时,绑定到它的脚本会在全局级别进行评估(根据
绑定
手册)。也就是说,如果是
绑定,则脚本myOk $cmd ;从字面上看,break 将被执行。因此,如果脚本运行时全局命名空间中不存在名为“cmd”的变量,则会触发您显示的错误。
要解决此问题,有多种方法:
$cmd
替换。为此,只需将 {} 替换为“”以允许变量替换,也就是说,如果您编写bind .$cmd; " myOk $cmd ; break "
绑定脚本将是myOK hello ;将
bind .$cmd; [list mycallback $cmd]
然后确保您已定义接受一个参数的mycallback
过程。通过这种方式,您可以编写通用事件处理程序,这些处理程序由绑定时所需的任何参数进行参数化。在所有情况下都要注意,由于您的 $cmd 在某些情况下可能会扩展为奇怪的东西,因此最好保护整个脚本免受这种情况的影响 - 这就是
[list ...]
所做的第二个示例(有关详细信息,请参阅此)。That's because when an event fires, the script bound to it gets
eval
uated at the global level (as per thebind
manual). That is, in case of your<Return>
binding, the scriptmyOk $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:
$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
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.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).