0

Consider the following situation:

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
}

Im trying to figure out how to (a) get a variable from the calling scope (b) have it available in all three procs and (c) writing any changes back into said variable.

(a) I would normally solve using 'upvar 1 $varName theVar' (b) I would normally solve with a namespace variable (c) As long as we only have one proc that would happen automaticly with (a) due to the fact that we would be working on a local alias of that variable

The problem is that upvar only works (at least as intended) in (1). I could use upvar in (1) and save/copy into a namespace variable, that would solve (a) and (b), but not (c).

I would be gratefull if someone could point me in the right direction here.

Also, as I'm relativly new to Tcl/Tk my concept might not be ideal, suggestions toward a better design are welcome too.

4

1 回答 1

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

文档:命名空间procputssetupvar变量

Snit 文档:手册页常见问题解答(常见问题解答也是一种介绍)

于 2014-08-18T15:31:50.020 回答