如何在tcl / tk中创建无模式对话框

时间:2013-12-12 20:55:08

标签: multithreading tcl tk modeless

我正在尝试建立一个无模式对话框,因为无论何时出现对话框都会停止在主gui中运行的实时进程,经过一些研究后我意识到导致实时部分停止的问题是对话框程序中的“vwait”命令。如何使我当前的对话框无模式,这样才不会影响后面的实时进程?每当我调用proc时,我应该将msgDialog放在不同的线程中吗?或者我还能以其他方式做到这一点?

TCL代码:

proc MsgDialog {w message type icon} \
{


if {![winfo exists $w]} { 
    set dialColor white

    image create photo .alert -format PNG -file alertIcon.png -width 40
    image create photo .question -format PNG -file questionicon.png

    toplevel $w -borderwidth 2 -relief raised -background $dialColor
    wm overrideredirect $w 1
    set x [expr { ( [winfo vrootwidth  $w] - 350  ) / 2 }]
    set y [expr { ( [winfo vrootheight $w] - 190 ) / 2 }]
    wm geometry $w 350x190+${x}+${y}


    frame $w.msgPnl -relief flat -borderwidth 1 -background $dialColor -width 280 -height 140
    place $w.msgPnl -x 0 -y 0

    frame $w.imgPnl -relief flat -borderwidth 1 -background $dialColor -width 50 -height 140 
    place $w.imgPnl -x 285 -y 0

    frame $w.btnPnl -relief flat -borderwidth 1 -background $dialColor -width 300 -height 50
    place $w.btnPnl -x 0 -y 130

    label $w.msgPnl.message -text $message -background $dialColor -justify center -wraplength 270 -font dialogFont
    pack $w.msgPnl.message -anchor center -pady 20 -padx 10 -expand 1 -fill both

    if {$type == "ok"} {

        button $w.btnPnl.okbut -text "OK" -background black -foreground white -relief flat -command {set _res "ok"} -width 8 -height 2 -highlightthickness 2 -font boldFont
        grid $w.btnPnl.okbut -row 1 -column 1 -padx 125

    } elseif {$type == "yesno"} {

        button $w.btnPnl.yes -text "Yes" -background black -foreground white -relief flat -command {set _res "yes"} -width 8 -height 2 -highlightthickness 2 -font boldFont
        button $w.btnPnl.no -text "No" -background black -foreground white -relief flat -command {set _res "no"} -width 8 -height 2 -highlightthickness 2 -font boldFont
        grid $w.btnPnl.yes -row 1 -column 1 -padx 50
        grid $w.btnPnl.no -row 1 -column 2

    } else {

        button $w.btnPnl.okbut -text "OK" -background $btnColor -relief flat -command {set _res "ok"} -width 8 -height 2
        pack $w.btnPnl.okbut -side top -anchor center
    }

    if {$icon == "alert"} {
        label $w.imgPnl.alertI -image .alert -compound top -background $dialColor
        pack $w.imgPnl.alertI -fill both -expand 1 -pady 20

    } elseif {$icon == "question"} {
        label $w.imgPnl.quest -image .question -compound top -background $dialColor
        pack $w.imgPnl.quest -fill both -expand 1 -pady 20
    } else {
        label $w.imgPnl.alertI -image .alert -compound top -background $dialColor
        pack $w.imgPnl.alertI -fill both -expand 1 -pady 20
    }

    raise $w
    vwait _res
    destroy $w
    return $::_res
}
}

我正在尝试这样的事情,但是当我得到无效的命令名称MsgDialog

 set tid [thread::create {thread::wait}]
 ::thread::send -async $tid {MsgDialog .dialog "Are you ready for measurement ?" yesno question} answer
 vwait answer

if {$answer == yes} {
 #do something
}

2 个答案:

答案 0 :(得分:1)

您的对话框proc基本上是模态的,因为它返回一个值。因此它会阻塞,直到用户响应,因为它无法返回其值,直到用户给它一个。

要使其无模式,请将其构建为仅创建自身并返回。然后按钮都需要调用procs(全局或具有一些完全限定的名称),它们会在你正在等待它的某个地方设置用户值,然后正确地销毁对话框。

这意味着您的“返回”值必须是全局的,窗口ID变量必须是全局的,处理程序proc / procs必须是全局的,并且您需要以某种方式触发您想要该值的任何处理太具体的应用程序让我猜。这是一项相当多的工作,但它比尝试合并线程库更容易。

答案 1 :(得分:0)

您是否尝试过删除vwait?模态对话框和非模态对话框之间的区别实际上只不过是调用vwait然后在键盘和鼠标上进行抓取的模态对话框。