I'm trying to make a modeless dialog, since whenever a dialog appears stops the real time process that is running in the main gui, after some reasearch i realize that the problem that is causing the real time part to stop is the "vwait" command in the dialog procedure. How could I make the my current dialog modeless so it doesn't affect the real time process in the back? Should I put the msgDialog in a different thread everytime i call the proc ? or what other way can I do it?
TCL CODE:
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
}
}
I was trying something like this, but when i get invalid command name 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
}
Your dialog proc is fundamentally modal, since it returns a value. It therefore blocks until the user responds, because it can't return its value until the user gives it one.
To make it modeless, build it to just create itself and return. The buttons all then need to call procs (either global or with some fully qualified name) that will set the user value in some place you're waiting for it, then destroy the dialog properly.
This means that your "return" value must be global, the window ID variable must be global, the handler proc/procs must be global, and you'll need to trigger whatever processing you want the value for in some way that's too application specific for me to guess. It's a fair bit of work, but it's easier than trying to incorporate the threading library.