开发者

Tcl/Tk: can't bind to Escape and Return

开发者 https://www.devze.com 2023-03-19 05:01 出处:网络
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:

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 evaluated 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 write bind .$cmd <Return> " myOk $cmd ; break " the bound script would be myOK 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 defined mycallback 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).

0

精彩评论

暂无评论...
验证码 换一张
取 消