2011-07-29 60 views
3

我有一个Tcl脚本控制自动测试仪。到目前为止,它是一个控制台程序,它在命令提示符下接受用户输入。一位同事写了一个可以由脚本启动的Tk GUI。我从来没有用过Tk,所以我不了解很多语法。Tcl/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 

} 

DisplayMessage是,只是在GUI更新文本标签的过程。

我不喜欢这个事实,即有一个全局变量gUserInterfaceBarCode用于保存序列号。有什么方法可以改用局部变量,并让程序返回该值?

如果我理解正确,如果行tkwait variable gUserInterfaceBarCode取出,此功能不会阻止,直到该变量更改。这是从GUI元素捕获用户输入的最佳方式吗?

回答

6

基本上你需要有一个等待的变量。不幸的是,<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] 

另一种方法是在返回前显式删除gUserInterfaceBarCode

tkwait variable ::gUserInterfaceBarCode 
set result $::gUserInterfaceBarCode 
unset ::gUserInterfaceBarCode 
return $result 

对于它的价值,Tk的核心实现使用的命名方式具有自己的内置对话框的实现,如“开放文件“对话框。

+1

Tk脚本还会在其自己的帮助程序中将任何事情变得模糊不清,因为它更容易处理范围。 –

+0

由于大多数Tcl OO扩展允许对象实例变量看起来像名称空间变量,所以您还可以使用OO扩展来封装变量。第三种方法是为所有状态使用一个全局数组变量,而不是为每个值使用一个变量名称。 – schlenk