Как мне обновить переменную через окно ТК по имени
Рассмотрим следующую ситуацию:
namespace eval ::mydialog {}
proc ::mydialog::show {w varName args} {
upvar 1 $varName theVar
# now I can access theVar
# (1)
# code defining/creating my window
# here some widgets for user interaction are created,
# some of which will call ::mydialog::_someCallback
wm protocol $w WM_DELETE_WINDOW [list ::mydialog::close $w]
}
proc ::mydialog::_someCallback {} {
# how do I access theVar here?
# (2)
}
proc ::mydialog::close { w } {
# here some changes are supposed to be written back into varName in the calling scope,
# how do I do that?!
# (3)
destroy $w
}
Я пытаюсь выяснить, как (а) получить переменную из вызывающей области видимости (б) сделать ее доступной во всех трех процессах и (в) записать любые изменения обратно в указанную переменную.
(a) Обычно я решаю, используя 'upvar 1 $varName theVar' (b) Обычно я решаю с помощью переменной пространства имен (c) Пока у нас есть только один процесс, который будет происходить автоматически с (a) из-за того, что мы будем работать над локальным псевдонимом этой переменной
Проблема в том, что upvar работает (по крайней мере, как задумано) в (1). Я мог бы использовать upvar в (1) и сохранить / скопировать в переменную пространства имен, которая бы решала (a) и (b), но не (c).
Я был бы благодарен, если бы кто-то мог указать мне правильное направление здесь.
Кроме того, поскольку я относительно новичок в Tcl/Tk, моя концепция может быть не идеальной, также приветствуются предложения по улучшению дизайна.
1 ответ
Я предлагаю вам использовать переменную пространства имен, которая хранит имя переменной, и upvar
используя глобальную область видимости.
namespace eval ::mydialog {
variable varName
}
proc ::mydialog::show {w _varName args} {
variable varName $_varName
upvar #0 $varName theVar
}
proc ::mydialog::_someCallback {} {
variable varName
upvar #0 $varName theVar
puts $theVar
}
proc ::mydialog::close { w } {
variable varName
upvar #0 $varName theVar
set theVar newval
}
set globalvar oldval
# => oldval
::mydialog::show {} globalvar
::mydialog::_someCallback
# => oldval
::mydialog::close {}
# => newval
puts $globalvar
# => newval
Обратите внимание, что подсветка синтаксиса не выполняется: #0 $varName theVar
на самом деле не комментарий.
Это работает и с переменными пространства имен: если у вас есть переменная с именем nsvar
в ::foobar
Пространство имен вы можете использовать его так:
set ::foobar::nsvar oldval
::mydialog::show {} ::foobar::nsvar
::mydialog::_someCallback
::mydialog::close {}
puts $::foobar::nsvar
с такими же эффектами.
Вы не можете, однако, использовать переменные, локальные для некоторой процедуры таким образом.
Один из способов сделать это действительно простым - использовать виджеты Snit вместо наборов процедур Tcl.
Документация: пространство имен, proc, put, set, upvar, переменная
Документация Snit: справочная страница, часто задаваемые вопросы (faq также служит своего рода введением)