我有一个打开TK顶层窗口的TCL脚本。在此窗口中,用户可以操作一些小部件(调用其他程序执行某些操作的按钮,检查按钮等)。当用户完成时,我希望他单击此窗口中的一个按钮,该按钮将导致顶层被破坏,并且打开它的过程将返回一个值。这就是我所拥有的:
proc openWindow {} {
set w .testwindow
catch {destroy $w}
toplevel $w
<here I setup all the widgets of the window>
button $w.btn -text "Exit" -command {
set ret [finishTest]
puts "returning $ret"
return $ret
}
pack $w.btn
pack $w
}
proc finishTest {} {
<here I evaluate the state of the $w widgets>
if {some condition} {
destroy $w
return 0
} else {
destroy $w
return -1
}
}
当我调用openWindow时,窗口显示并按原样运行,当我单击“退出”按钮时,它会正确打印“returns:$ ret”但是我会调用puts [openWindow]它只会打印一个没有其他的新行单击按钮后的字符。
我定义了$ w变量globaly,以便我可以在finishTest过程中的openWindow之外访问它。
感谢您的建议!
答案 0 :(得分:0)
回调不会影响局部变量,并且您的openWindow
当前不会在返回之前等待回调处理。为了使其工作,您必须使用vwait
(或tkwait
)让事件循环运行,直到执行回调。 (它通过运行辅助事件循环来实现这一点,它确实占用了堆栈空间,因此请注意重入问题。)查看下面标记的行(finishTest
未更改)。
proc openWindow {} {
global ret; #########################
set w .testwindow
catch {destroy $w}
toplevel $w
<here I setup all the widgets of the window>
button $w.btn -text "Exit" -command {
set ret [finishTest]; #########################
}
pack $w.btn
pack $w
vwait ret; #########################
puts "returning $ret"; #########################
return $ret; #########################
}
如果可以从coroutine内部(即可挂起的堆栈上下文)完成对openWindow
的调用,则可以使用Tcl 8.6的协同程序稍微解开这个混乱。这将使代码的这一部分看起来更像(再次注意标记的行):
proc openWindow {} {
set w .testwindow
catch {destroy $w}
toplevel $w
<here I setup all the widgets of the window>
button $w.btn -text "Exit" -command [info coroutine]; #########################
pack $w.btn
pack $w
yield; #########################
set ret [finishTest]; #########################
puts "returning $ret"; #########################
return $ret; #########################
}