【问题标题】:How to return value from the TK toplevel window?如何从 TK 顶层窗口返回值?
【发布时间】:2014-09-29 11:17:23
【问题描述】:

我有一个打开 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 时,窗口显示并正常运行,当我单击退出按钮时,它正确打印“returning: $ret”,但是当我调用 puts [openWindow] 时,它只打印一个新行而没有其他点击按钮后的字符。

我全局定义了 $w 变量,以便我可以在 finishTest 过程中的 openWindow 之外访问它。

感谢您的建议!

【问题讨论】:

    标签: return tcl tk


    【解决方案1】:

    回调不能影响局部变量,并且您的 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;                               #########################
    }
    

    如果对openWindow 的调用可以从coroutine 内部完成(即,可挂起的堆栈上下文),则可以使用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;                                            #########################
    }
    

    【讨论】:

    • 谢谢你,Donal,这解决了我从 proc 返回值的问题!然而,正如我在对 Hoodiecrow 的回答中所说,我必须使用 Tcl/Tk8.3 的非标准解释器,其行为与 Wish 完全不同。它不允许我与小部件进行交互,我可以移动或调整窗口大小,但内部没有任何反应。我知道这可能与我最初提出的问题完全不同,但是如果您有建议,我会很感激,谢谢! :)
    猜你喜欢
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多