I figured it out.
I replaced this:
catch { tkwait visibility $form }
with
catch {
tkwait visibility $form grab release $form
}
and now it works.
Below is a tiny program.
The "About" form is created and destroyed. So you can click About then
close the About form, then repeat as often as you like.
The "Options" form is supposed to be shown and hidden. But once you
click it and then close it, the entire app is blocked. So clearly I'm
doing something wrong.
Here's the code using Tcl/Tk 9.0b2 on Linux.
#!/usr/bin/env wish9
if {[info exists env(TK_SCALING)]} { tk scaling $env(TK_SCALING) }
proc prepare_modal {form} {
wm withdraw $form wm attributes $form -type dialog wm transient
$form .
}
proc show_modal {form {focus_widget ""}} {
wm deiconify $form raise $form focus $form if {$focus_widget ne ""}
{
focus $focus_widget
}
catch {grab set $form}
catch {tkwait visibility $form}
}
variable optionsForm
proc main {} {
wm title . "Dialog Tests"
wm minsize . 240 240 wm attributes . -type dialog ttk::button
.optionsButton -text Options… -underline 1 \
-command on_options
ttk::button .aboutButton -text About -underline 1 -command on_about
pack .optionsButton -side top pack .aboutButton -side top
}
proc on_options {} {
if {![info exists ::optionsForm]} {
puts "on_options init"
set ::optionsForm [toplevel .optionsForm] prepare_modal
.optionsForm wm protocol .optionsForm WM_DELETE_WINDOW {wm
withdraw .optionsForm}
ttk::label .optionsForm.label -text Options pack
.optionsForm.label
}
puts on_options ;# TODO use show_modal hide/show show_modal
$::optionsForm ;# TODO give focus widget
}
proc on_about {} {
toplevel .aboutForm prepare_modal .aboutForm wm protocol .aboutForm
WM_DELETE_WINDOW {destroy .aboutForm} ttk::label .aboutForm.label
-text About pack .aboutForm.label show_modal .aboutForm
}
main
Below is a tiny program.
The "About" form is created and destroyed. So you can click About then
close the About form, then repeat as often as you like.
The "Options" form is supposed to be shown and hidden. But once you click
it and then close it, the entire app is blocked. So clearly I'm doing something wrong.
On Fri, 21 Jun 2024 09:55:13 +0000, Mark Summerfield wrote:
Below is a tiny program.
The "Options" form is supposed to be shown and hidden. But once you
click it and then close it, the entire app is blocked. So clearly I'm
doing something wrong.
I think I have solved it this time.
I added this proc:
proc hide_modal {form} {
wm withdraw $form
grab release $form
}
and changed the protocol call to:
wm protocol .optionsForm WM_DELETE_WINDOW {hide_modal .aboutForm}
It seems to work, but is this now correct?
Mark Summerfield <mark@qtrac.eu> wrote:
Below is a tiny program.
The "About" form is created and destroyed. So you can click About then
close the About form, then repeat as often as you like.
The "Options" form is supposed to be shown and hidden. But once you
click it and then close it, the entire app is blocked. So clearly I'm
doing something wrong.
Based on your code you are showing the options as a "modal" dialog.
Modal means it blocks the rest of the app. Withdrawing the window does
not change its "modalness". You need to not only withdraw the window
but also turn off the "modalness" of the window at the same time.
I.e., you need to "grab release" on the window as part of withdrawing
it.
As a suggestion, you might also consider making the options window 'non-modal' in that it can be open and the rest of the app can still function. Modality is more often evil than anything else in a GUI.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 970 |
Nodes: | 10 (2 / 8) |
Uptime: | 104:41:00 |
Calls: | 12,740 |
Calls today: | 2 |
Files: | 186,574 |
Messages: | 3,171,665 |