2013-12-12 3 views
1

Я пытаюсь создать немодальный диалог, поскольку всякий раз, когда появляется диалоговое окно, останавливается процесс реального времени, который выполняется в главном gui, после некоторого повторного поиска я понимаю, что проблема, вызывает остановку в реальном времени части - это команда «vwait» в процедуре диалога. Как я могу сделать мой текущий диалог немодальным, чтобы он не влиял на процесс реального времени в спине? Должен ли я помещать msgDialog в другой поток каждый раз, когда я вызываю proc? или каким другим способом я могу это сделать?Как создать немодальное диалоговое окно в tcl/tk

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 
} 

ответ

1

Ваш диалог proc в основном модальный, так как он возвращает значение. Поэтому он блокируется до тех пор, пока пользователь не ответит, потому что он не может вернуть свое значение, пока пользователь не даст его.

Чтобы сделать его немодальным, создайте его, чтобы просто создать себя и вернуться. Теперь всем кнопкам нужно вызывать procs (глобальные или с некоторым полным именем), которые будут устанавливать значение пользователя в каком-то месте, которое вы его ожидаете, а затем уничтожить диалог должным образом.

Это означает, что ваше значение «return» должно быть глобальным, переменная окна ID должна быть глобальной, обработчик proc/procs должен быть глобальным, и вам нужно будет инициировать любую обработку, в которой вы хотите получить значение в некотором роде это слишком специфическое приложение для меня, чтобы догадаться. Это честная работа, но это проще, чем пытаться включить библиотеку потоков.

+1

Хорошим способом обработки немодального взаимодействия является вызов вызывающего абонента MsgDialog для запуска обратного вызова при завершении взаимодействия. (Затем вы можете распутать поток выполнения, чтобы сделать что-то, что выглядит модально в работе с помощью сопрограмм 8.6.) –

+0

Спасибо Эрик, я думаю, что понимаю, что вы имеете в виду, что вы имеете в виду идентификатор окна? –

+0

В вашем коде это было $ w, которое является локальной переменной. Значение, хранящееся в $ w, должно быть доступно для proc, который выполняет уничтожение окна. И предложение Донала о прохождении обратного вызова - это надежный способ обработки имени proc для вызова нажатием кнопки без жесткого кодирования. –

0

Вы пробовали просто удалив VWait? Разница между модальным диалогом и немодальным - это не что иное, как модальный диалог, вызывающий vwait, а затем захват клавиатуры и мыши.

+0

Настоящий модальный диалог также устанавливает захват. –

+0

Хорошая точка. Спасибо, Донал. Я уточню свой ответ. –