Tcl / Tk:无法绑定到Escape和Return

时间:2011-07-11 15:59:50

标签: tcl bind tk

我的Tcl / Tk代码中无法bind EscapeReturn个键。以下代码重现了该错误。当我点击EscEnter键时,我收到以下错误消息:

错误:无法读取“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

1 个答案:

答案 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了解更多信息)。