Tcl / Tk: не может связываться с Escape и Return - PullRequest
1 голос
/ 11 июля 2011

Я не могу bind ключи Escape и Return в моем коде Tcl / Tk.Следующий код воспроизводит ошибку.Когда я нажимаю клавишу 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

1 Ответ

5 голосов
/ 11 июля 2011

Это потому, что когда событие запускается, связанный с ним скрипт получает 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 ...]делает во втором примере (см. this для получения дополнительной информации).

...