我的Tcl / Tk代码中无法bind
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
答案 0 :(得分:5)
那是因为当一个事件触发时,绑定到它的脚本在全局级别获得eval
(根据bind
manual)。也就是说,在<Return>
绑定的情况下,脚本myOk $cmd ; break
将按字面意思执行。因此,如果在脚本运行时全局命名空间中没有名为“cmd”的变量,则会触发您显示的错误。
要解决此问题,有以下几种方法:
$cmd
替换。要执行此操作,只需将{}替换为“”以允许变量替换,也就是说,如果您编写bind .$cmd <Return> " myOk $cmd ; break "
,则绑定脚本将为myOK hello ; break
bind .$cmd <Return> [list mycallback $cmd]
然后确保已定义mycallback
过程接受一个参数。通过这种方式,您可以编写通用事件处理程序,这些处理程序通过绑定时所需的任何参数进行参数化。namespace code
或类似工具使脚本在指定的命名空间中执行,该命名空间已定义指定的变量。在所有情况下都要注意,因为你的$ cmd可能会在某些情况下扩展到奇怪的东西,所以保护整个脚本免受这种情况的影响是个好主意 - 这就是[list ...]
在第二个例子中的作用(见this了解更多信息)。