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

Ana*_*and 1 bind tk-toolkit tcl

我不能用我的Tcl/Tk代码中bindEscapeReturn键.以下代码重现了该错误.当我按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
Run Code Online (Sandbox Code Playgroud)

kos*_*tix 5

这是因为当一个事件触发时,绑定到它的脚本会eval在全局级别上进行操作(根据bind手册).也就是说,在<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 ...]第二个例子中的内容(有关详细信息,请参阅内容).