Tcl Tk:如何使用-command传递变量值?

Tcl Tk:如何使用-command传递变量值?,tcl,tk,Tcl,Tk,我得到一个错误: button .mltext.button -text "Apply" -command {set top_tlbl [update_text $top_tlbl $spc ] } 如何将变量的值传递给update_text函数 也许我可以从理解这一点开始: can't read "spc": no such variable while executing "update_text $top_tlbl $spc " invoked from within ".mltext.

我得到一个错误:

button .mltext.button -text "Apply" -command {set top_tlbl [update_text $top_tlbl $spc ] }
如何将变量的值传递给update_text函数

也许我可以从理解这一点开始:

can't read "spc": no such variable
while executing
"update_text $top_tlbl $spc "
invoked from within
".mltext.button invoke"
据我所知,最后一个命令应该生成expr 2+2,这与第一个命令相同——那么,为什么TCL会有问题呢


谢谢。

您可能只需调用
update\u text
,并使
top\u tlbl
成为一个全局函数,并从调用的函数中进行设置,而不是返回

通常最简单的方法是尝试调用一个简单的函数,并使用
list
确保所有内容都被正确引用

(System32) 3 % expr 2 + 2
4
(System32) 4 % list expr 2 + 2
expr 2 + 2
(System32) 5 % [list expr 2 + 2]
invalid command name "expr 2 + 2"
(System32) 6 % 
当您定义此按钮及其命令时,这将捕获
top\u tlbl
spc
的当前值。如果在按下按钮时需要这些值,则可能需要传递变量名称,并使用
变量
全局
命令


无论如何,规则是大括号
{}
中的内容不执行任何替换。因此,
{$v}
被传递给被调用方,与-dollar v完全相同。使用
list
或双引号可以执行变量替换,因此可以传递变量的值。List可以正确处理变量值可能包含空格等情况下的引用。

您可能只需调用
update\u text
,并使
top\u tlbl
成为全局变量,并从调用的函数中设置,而不是返回

通常最简单的方法是尝试调用一个简单的函数,并使用
list
确保所有内容都被正确引用

(System32) 3 % expr 2 + 2
4
(System32) 4 % list expr 2 + 2
expr 2 + 2
(System32) 5 % [list expr 2 + 2]
invalid command name "expr 2 + 2"
(System32) 6 % 
当您定义此按钮及其命令时,这将捕获
top\u tlbl
spc
的当前值。如果在按下按钮时需要这些值,则可能需要传递变量名称,并使用
变量
全局
命令


无论如何,规则是大括号
{}
中的内容不执行任何替换。因此,
{$v}
被传递给被调用方,与-dollar v完全相同。使用
list
或双引号可以执行变量替换,因此可以传递变量的值。列表正确地处理变量值可能包含空格等情况下的引用。

-当单击按钮时,将在全局上下文中调用命令{set top_tlbl[update_text$top_tlbl$spc]}
。您的变量
spc
是否可以在全局上下文中访问?尝试显式指定变量的命名空间,例如
$::spc



expr 2+2
“expr 2+2”
不一样。Tcl标识符可以包含空格,
“expr 2+2”
是未找到的整个标识符。

-当单击按钮时,将在全局上下文中调用命令{set top\u tlbl[update\text$top\u tlbl$spc]}
。您的变量
spc
是否可以在全局上下文中访问?尝试显式指定变量的命名空间,例如
$::spc



expr 2+2
“expr 2+2”
不一样。Tcl标识符可以包含空格,
“expr 2+2”
是未找到的整个标识符。

在您的
expr
示例中,我们从计算单词开始

expr 2+2
有四个词:
expr
2
+
2
。第一个是命令名,
expr
,其他的作为参数传递;
expr
的文档说明,它连接参数并计算结果表达式

list expr 2+2
有五个词:
list
expr
2
+
2
。第一个是命令名,
list
,其他的作为参数传递;
list
的文档说,它返回的列表的参数为元素。虽然我们在这里没有明确地看到它,但它确实引入了生成单个无替换命令所需的引用。好的Tcl代码在生成代码时会大量使用
list

[list expr 2+2]
有一个单词,它是调用
list expr 2+2
的结果。如果你直接把它输入Tcl,它有一个奇怪但合法的命令名,而你可能没有一个叫做它的命令。因此你会得到一个错误


现在让我们考虑一下:

button .mltext.button -text "Apply" \
    -command [list update_text $top_tlbl $spc]
根据您的评论,您正在过程中调用此函数。这意味着您需要在回调中绑定变量(在
uplevel\0
中进行计算,可能在当前过程返回后很久),而不立即执行回调。奇怪的是,看起来您也在运行时更改
top\tlbl

让我们从思考最里面的部分开始。我们可以使用
list
很好地生成它(忽略不同的生存期绑定):

现在我们只需要让其他部分也能工作。这就是它变得烦躁的地方,你最终会得到这样的结果:

list update_text $top_tlbl $spc
现在,让我们来解决生命周期问题:

… -command "set top_tlbl \[[list update_text $top_tlbl $spc]\]"
这种事情在复杂的回调中非常容易出错!在这一点上,有一个小助手程序要容易得多(也是一个很好的实践):

… -command "set top_tlbl \[update_text \$top_tlbl [list $spc]\]"
然后您可以执行以下操作(注意:传递
top\tlbl
的名称,而不是值):

全局变量名的使用可能会被认为是有问题的,除非您必须记住,全局名称空间主要由您的应用程序拥有。如果你想为你的应用程序在全局变量中存储变量,那么就这样做吧!你有完全的权利

当然,库代码需要更加小心。那里的常用技术包括在其他名称空间中使用变量(Tk不这样做)
proc do_update_text {varname value} {
    upvar #0 $varname var
    set var [update_text $var $value]
}
… -command [list do_update_text top_tlbl $spc]
… -command [list do_update_text ::mynamespace::top_tlbl $spc]