button .mltext.button -text "Apply" -command {set top_tlbl [update_text $top_tlbl $spc ] }
我收到错误:
can't read "spc": no such variable
while executing
"update_text $top_tlbl $spc "
invoked from within
".mltext.button invoke"
如何将变量值传递给update_text函数?
也许我可以从理解这一点开始:
(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 %
据我说,最后一个应该生成expr 2 + 2,这与第一个命令相同 - 那么,为什么TCL有问题?
谢谢..
答案 0 :(得分:3)
在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 {set top_tlbl [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]\]"
这种事情在复杂的回调中更容易出错!那时,有一个小帮手程序会更容易(并且良好实践):
proc do_update_text {varname value} {
upvar #0 $varname var
set var [update_text $var $value]
}
然后你可以这样做(注意:传递top_tlbl
的名称,而不是值:)
… -command [list do_update_text top_tlbl $spc]
全局变量名的使用可能被认为是有问题的,除非您必须记住全局命名空间主要由您的应用程序拥有。如果您想为您的应用程序存储全局变量,请执行此操作!你有完整的权利。
图书馆代码当然需要更加小心。通常的技术包括在其他命名空间中使用变量(Tk在内部执行此操作)或在对象中使用变量。代码实际上并没有那么复杂;它仍然建立在使用上面列出的帮助程序的做法上。传递命名空间变量名称非常简单:
… -command [list do_update_text ::mynamespace::top_tlbl $spc]
答案 1 :(得分:2)
-command {set top_tlbl [update_text $top_tlbl $spc]}
。您的变量spc
在全局范围内是否可访问?尝试明确指定变量的命名空间,例如$::spc
。
expr 2 + 2
和"expr 2 + 2"
不一样。 Tcl标识符可以包含空格,"expr 2 + 2"
是整个标识符,找不到。
答案 2 :(得分:1)
您应该只调用update_text
并让top_tlbl
成为全局变量并从被调用函数设置而不是返回。
通常最简单的方法是尝试调用一个简单的函数并使用list
来确保所有内容都被正确引用。
button .mltext.button -text "Apply" \
-command [list update_text $top_tlbl $spc]
当您定义此按钮及其命令时,这将捕获top_tlbl
和spc
的当前值。如果您在按按钮时想要值,那么您可能应该传递变量的名称并使用variable
或global
命令。
无论如何,规则是大括号{}
内的东西没有对它们进行替换。所以{$v}
正好传递给被调用者 - 美元v。使用list
或双引号允许执行变量替换,因此传递变量的值。 List适当地处理变量值可能包含空格等情况的引用。