我有一个控制自动测试仪的Tcl脚本.到目前为止,它是一个控制台程序,它在命令提示符下输入用户输入.一位同事写了一个可以由脚本启动的Tk GUI.我自己从未使用过Tk,所以我不理解很多语法.
在测试开始时,脚本必须从操作员处获取单元序列号.这是我的同事写的那个功能:
proc GetSerialNumber {} {
global gUserInterfaceBarCode
DisplayMessage "Enter serial number:"
.c.serialnumberbox configure -state normal
focus .c.serialnumberbox
bind .c.serialnumberbox <Return> { set gUserInterfaceBarCode [.c.serialnumberbox get] }
tkwait variable gUserInterfaceBarCode
#grid forget .c.serialnumberbox
.c.serialnumberbox configure -state disabled
}
Run Code Online (Sandbox Code Playgroud)
DisplayMessage 是一个简单地更新GUI上的文本标签的过程.
我不喜欢有一个gUserInterfaceBarCode用于保存序列号的全局变量这一事实.有没有办法使用局部变量而让程序返回该值?
如果我理解正确,如果该行tkwait variable gUserInterfaceBarCode被取出,该函数将不会阻塞,直到该变量发生变化.这是从GUI元素捕获用户输入的最佳方法吗?
从根本上说,你需要有一个变量来等待.不幸的是,它的代码<Return>是在不同的上下文(全局上下文)中执行的,而不是proc中的代码,并且代码无法解决proc中的局部变量.
但是,它本身不需要全局变量 - 它只需要全局可寻址,我的意思是你可以使用命名空间变量,如果这让你感觉更好:
namespace eval GetSerialNumber {
proc GetSerialNumber {} {
DisplayMessage "Enter serial number:"
.c.serialnumberbox configure -state normal
focus .c.serialnumberbox
bind .c.serialnumberbox <Return> { set ::GetSerialNumber::result [.c.serialnumberbox get] }
tkwait variable ::GetSerialNumber::result
.c.serialnumberbox configure -state disabled
return $::GetSerialNumber::result
}
}
set serialNum [GetSerialNumber::GetSerialNumber]
Run Code Online (Sandbox Code Playgroud)
另一种选择是gUserInterfaceBarCode在返回之前明确删除:
tkwait variable ::gUserInterfaceBarCode
set result $::gUserInterfaceBarCode
unset ::gUserInterfaceBarCode
return $result
Run Code Online (Sandbox Code Playgroud)
对于它的价值,Tk核心实现将命名空间方法用于其自己的内置对话框实现,如"打开文件"对话框.