如何通过名称的tk窗口更新变量

时间:2014-08-18 14:25:07

标签: namespaces tcl tk upvar

考虑以下情况:

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很新,我的概念可能不太理想,也欢迎提出改进设计的建议。

1 个答案:

答案 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过程的集合。

文档:namespaceprocputssetupvarvariable

Snit文档:man pagefaq(常见问题解答也是一种介绍)