1

我正在尝试制作一个无模式对话框,因为每当出现对话框时都会停止在主 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
}
4

2 回答 2

1

您的对话过程基本上是模态的,因为它返回一个值。因此它会阻塞直到用户响应,因为在用户给它一个值之前它不能返回它的值。

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

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

于 2013-12-13T01:11:32.053 回答
0

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

于 2013-12-12T22:54:51.380 回答