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

时间:2015-10-26 21:13:02

标签: tcl tk

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有问题?

谢谢..

3 个答案:

答案 0 :(得分:3)

expr的示例中,我们首先计算单词。

expr 2 + 2有四个字:expr2+2。第一个是命令名expr,其他名称作为参数传递; expr的文档说它连接了它的参数并评估了结果表达式。

list expr 2 + 2有五个字:listexpr2+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_tlblspc的当前值。如果您在按按钮时想要值,那么您可能应该传递变量的名称并使用variableglobal命令。

无论如何,规则是大括号{}内的东西没有对它们进行替换。所以{$v}正好传递给被调用者 - 美元v。使用list或双引号允许执行变量替换,因此传递变量的值。 List适当地处理变量值可能包含空格等情况的引用。