Как мне обновить переменную через окно ТК по имени

Рассмотрим следующую ситуацию:

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 также служит своего рода введением)

Другие вопросы по тегам