开发者

Tcl/Tk bind requires global variable?

I have a Tcl script controlling an automated tester. So far it was a console program that took user input at the command prompt. A colleague wrote a Tk GUI that can be launched by the script. I have never used Tk myself, so I don't understand a lot of the syntax.

开发者_运维问答

At the beginning of the test the script must get a unit serial number from the operator. This is the function that my colleague wrote to do that:

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 is a procedure that simply updates a text label on the GUI.

I don't like the fact that there is a global variable gUserInterfaceBarCode that is used to hold the serial number. Is there any way to use a local variable instead and have the procedure return that value?

If I understand correctly, if the line tkwait variable gUserInterfaceBarCode is taken out this function will not block until that variable changes. Is this the best way to capture user input from a GUI element?


Fundamentally you need to have a variable to wait on. Unfortunately, the code for the <Return> is executed in a different context (the global context) than the code inside your proc, and there's no way for that code to address the local variables in your proc.

However, it doesn't have to a global variable, per se -- it just needs to be globally addressable, by which I mean you could use a namespace variable instead, if that makes you feel better about it:

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]

Another alternative would be to explicitly delete gUserInterfaceBarCode before returning:

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

For what it's worth, the Tk core implementation uses the namespace approach for its own built-in dialog implementations, like the "Open File" dialog box.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜