I have gotten into a situation in which I have a modal dialog that
launches a modal dialog, and then, if there is a particular problem
that could occur, the second one launches a third modal dialog. Based
on that problem, the user might want to cancel out of the whole
operation. And so the final dialog is a custom dialog that has a
button to "Cancel out of this whole operation". I think there is even
another object in the hierarchy, about 4 levels or so.
In general, what's the best way to dismiss all of these objects
without getting into having to pass a close signal from one obect to
the next AND without getting into some problem about the object no
longer existing? (Like I tried just .Destroy() on the grandparent
dialog but the whole app then just locked up).
In general, what's the best way to dismiss all of these objects
without getting into having to pass a close signal from one obect to
the next AND without getting into some problem about the object no
longer existing?
The only practical option is to pass a close signal up the layers. Each
of these modal dialogs is waiting for the next one to finish, right?
So, the #4 dialog returns a cancel status. The #3 dialog sees that,
closes #4, and returns a cancel status. The #2 dialog sees that, closes #3, and returns a cancel status. And so on.
···
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
Thanks. I realize in reading this and thinking about these issues, I
have never been clear enough on the various ways for dialogs,
particularly custom modal ones, to return info to their parents and
close or be closed.
For example, what're the differences between these various ways? Is
there a preferred approach? (here "self" refers to the modal dialog).
Generally, is there some best practice for *custom* modal dialogs that
have buttons other than just OK and CANCEL to return info to their
parents?
···
On Fri, Jul 26, 2013 at 1:27 PM, Tim Roberts <timr@probo.com> wrote:
C M wrote:
In general, what's the best way to dismiss all of these objects
without getting into having to pass a close signal from one obect to
the next AND without getting into some problem about the object no
longer existing?
The only practical option is to pass a close signal up the layers. Each
of these modal dialogs is waiting for the next one to finish, right?
So, the #4 dialog returns a cancel status. The #3 dialog sees that,
closes #4, and returns a cancel status. The #2 dialog sees that, closes #3, and returns a cancel status. And so on.
When you fire up a modal dialog by calling ShowModal, that starts a
brand new message loop dedicated solely to that dialog. The calling
thread cannot proceed while that message loop is running. That's what
makes it "modal". The only way to get that message loop to exit is by
calling self.EndModal. That hides the dialog window, and sets the value
that should be returned from ShowModal. If you let the dialog Destroy
itself, that takes down the window, but does not exist the modal message
loop. That's probably the hang you say.
Now, SOMEONE has to destroy the window, but it needs to be after the
dialog has completed. So, the idiomatic sequence is:
dlg = wx.MyModalDialog(...)
result = dlg.ShowModal()
dlg.Destroy()
There are many ways to return values from one to the other. The "dlg"
variable is still viable between the ShowModal and the call to Destroy,
so in addition to the single integer returned from ShowModal, the dialog
class could tuck information into instance variables that the parent
accesses:
Calling self.GetParent().message is kind of the "push-model" of data
exchange. It's a personal preference, but it has always seemed cleaner
to me if the child dialog doesn't know anything about its parent. Let
the parent do the driving. However, calling self.GetParent().message
doesn't do anything to shut down the modal dialog. For that, you need
EndModal.
···
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.