考虑以下情况:
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)从调用范围中获取变量(b)在所有三个过程中都有它并且(c)将任何更改写回到所述变量中。
(a)我通常会使用'upvar 1 $ varName theVar'来解决 (b)我通常会使用命名空间变量来解决 (c)只要我们只有一个proc会自动发生(a)由于我们将在该变量的本地别名上工作
问题是upvar只能在(1)中起作用(至少按预期)。 我可以在(1)中使用upvar并保存/复制到命名空间变量中,这将解决(a)和(b),但不能解决(c)。
如果有人能指出我在这里正确的方向,我将不胜感激。
另外,由于我对Tcl / Tk很新,我的概念可能不太理想,也欢迎提出改进设计的建议。
答案 0 :(得分: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过程的集合。