Close main frame after all child frames closed?

In my app, I have a main frame that can open a number of other child frames. The child frames have on_close handlers
that check if any data needs to be saved, possibly presents
a dialog, and either closes or veto's the child frame's close.

In the main frame's on_close handler, I close all the child windows and then want to close the main window if all the child windows are closed, or not, if any are still open (because the user canceled a save dialog or some other problem closing a child window.).

However, when I check the child windows they all seem to still open after I have closed them. I realize from the docs that calling Close() just schedules their close rather
than actually closing them immediately, but I am not sure
how to get the results I want. I have tried putting Yield()
calls between closing the child windows and the check if they're closed. And I have put Destroy() calls in the child on_close handlers. These did not help.

How should the main frame check if all the child frames were closed?

Demo program attached. Thanks for any help.

close2.py (1.11 KB)

In my app, I have a main frame that can open a number of
other child frames. The child frames have on_close handlers
that check if any data needs to be saved, possibly presents
a dialog, and either closes or veto's the child frame's close.

In the main frame's on_close handler, I close all the child
windows and then want to close the main window if all the
child windows are closed, or not, if any are still open
(because the user canceled a save dialog or some other
problem closing a child window.).

However, when I check the child windows they all seem to
still open after I have closed them. I realize from the
docs that calling Close() just schedules their close rather
than actually closing them immediately,

You'll have to .Destroy() them AFAIK.

How should the main frame check if all the child frames
were closed?

wx.GetTopLevelWindows() gives you a list (of which I learned
just recently :slight_smile:

Karsten

···

On Fri, Jul 17, 2009 at 03:46:31PM -0600, Stuart McGraw wrote:
--
GPG key ID E4071346 @ wwwkeys.pgp.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

Hi Stuart,

···

On Jul 17, 4:46 pm, Stuart McGraw <smcg4...@frii.com> wrote:

In my app, I have a main frame that can open a number of
other child frames. The child frames have on_close handlers
that check if any data needs to be saved, possibly presents
a dialog, and either closes or veto's the child frame's close.

In the main frame's on_close handler, I close all the child
windows and then want to close the main window if all the
child windows are closed, or not, if any are still open
(because the user canceled a save dialog or some other
problem closing a child window.).

However, when I check the child windows they all seem to
still open after I have closed them. I realize from the
docs that calling Close() just schedules their close rather
than actually closing them immediately, but I am not sure
how to get the results I want. I have tried putting Yield()
calls between closing the child windows and the check if
they're closed. And I have put Destroy() calls in the
child on_close handlers. These did not help.

How should the main frame check if all the child frames
were closed?

Demo program attached. Thanks for any help.

[close2.py1K ]import sys, pdb, wx, time

def main():
app = wx.App (redirect=0)
frame = MainFrame (None)
frame.Show (True)
app.MainLoop()

class MainFrame (wx.Frame):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, -1, "Main", size=(320,270))
self.Bind (wx.EVT_CLOSE, self.onClose)
for n in (1,2,3): chld = ChildFrame (self, n)

def onClose \(self, evt\):
    chlds = \[x for x in self\.GetChildren\(\) if isinstance\(x, ChildFrame\)\]
    print &gt;&gt;sys\.stderr, &quot;Initially open: %r&quot; % \[x\.GetLabel\(\) for x in chlds\]
    for x in chlds:
        x\.Close\(\)
    wx\.Yield\(\);time\.sleep\(\.5\); wx\.Yield\(\)
    chlds = \[x for x in self\.GetChildren\(\) if isinstance\(x, ChildFrame\)\]
    print &gt;&gt;sys\.stderr, &quot;Still open: %r&quot; % \[x\.GetLabel\(\) for x in chlds\]
    if chlds:  evt\.Veto\(\)
    else: evt\.Skip\(\)

class ChildFrame (wx.Frame):
def __init__(self, parent, numb):
wx.Frame.__init__ (self, parent, -1, "Child %d" % numb, size=(320,270))
self.Bind (wx.EVT_CLOSE, self.onClose)
self.Show()

def onClose \(self, evt\):
    name = self\.GetLabel\(\)
    print &gt;&gt;sys\.stderr, &quot;closing child %s&quot; % name
    self\.Destroy\(\)

if __name__ == '__main__': main ()

I think what you want is the method ProcessPendingEvents, but that
seems to be only callable from the app object and I can't figure out
how to get a handle on that from your sample. Hopefully one of the
others knows...

- Mike

Mike Driscoll wrote:

I think what you want is the method ProcessPendingEvents, but that
seems to be only callable from the app object and I can't figure out
how to get a handle on that from your sample. Hopefully one of the
others knows...

wx.GetApp()

···

--
Robin Dunn
Software Craftsman

Stuart McGraw wrote:

In my app, I have a main frame that can open a number of other child frames. The child frames have on_close handlers
that check if any data needs to be saved, possibly presents
a dialog, and either closes or veto's the child frame's close.

In the main frame's on_close handler, I close all the child windows and then want to close the main window if all the child windows are closed, or not, if any are still open (because the user canceled a save dialog or some other problem closing a child window.).

However, when I check the child windows they all seem to still open after I have closed them. I realize from the docs that calling Close() just schedules their close rather
than actually closing them immediately, but I am not sure
how to get the results I want. I have tried putting Yield()
calls between closing the child windows and the check if they're closed. And I have put Destroy() calls in the child on_close handlers. These did not help.

How should the main frame check if all the child frames were closed?

The return value of Close() is True if the child frame was closed, or False if the child frame's EVT_CLOSE handler vetoed the close.

···

--
Robin Dunn
Software Craftsman

Robin,

···

On Jul 20, 4:37 pm, Robin Dunn <ro...@alldunn.com> wrote:

Mike Driscoll wrote:
> I think what you want is the method ProcessPendingEvents, but that
> seems to be only callable from the app object and I can't figure out
> how to get a handle on that from your sample. Hopefully one of the
> others knows...

wx.GetApp()

--
Robin Dunn

I knew there was a GetApp(), but I could not find it. Drat!

- Mike