Reputation: 391
My wxPython application consists of a main window and an arbitrary number of secondary windows that the user can choose to launch. When the user closes the main window, I want the application to exit (and all other windows to close too, naturally). The standard behavior is for the application to exit only when the user closes the last window.
Do I need to program a global list of all windows, just to iterate and close them all to exit the application?
Is my desired GUI behavior really so non-standard that it takes custom code to implement? I expected a simple App.exit()
call or similar.
EDIT: I now found https://docs.wxpython.org/wx.PyApp.html#wx.PyApp.SetExitOnFrameDelete
Allows the programmer to specify whether the application will exit when the top-level frame is deleted.
But it doesn't work for me.
Here is a short example. Closing frame1 should exit the application, but it doesn't. It's necessary to close both windows.
import wx
class MainFrame(wx.Frame):
def __init__(self, title, *args, **kwargs):
super().__init__(None, *args, **kwargs)
self.Title = title
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
if __name__ == '__main__':
wx_app = wx.App()
frame1 = MainFrame("Close me to exit")
frame2 = MainFrame("Secondary window")
wx_app.SetTopWindow(frame1)
wx_app.SetExitOnFrameDelete(True)
wx_app.MainLoop()
Upvotes: 1
Views: 86
Reputation: 22443
The issue is that you have 2 top level frames.
The App
closes when the last top level frame closes, so usually there is 1 top level frame and subsequent frames have that as their parent
.
With this arrangement, when the parent closes, the child frames close as well.
See: https://docs.wxpython.org/app_overview.html#application-shutdown
Alternatively see: https://docs.wxpython.org/wx.functions.html#wx.Exit
For your example:
import wx
class MainFrame(wx.Frame):
def __init__(self, title, *args, **kwargs):
super().__init__(None, *args, **kwargs)
self.Title = title
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.frame2 = SecondaryFrame(parent=self, title="Secondary")
def OnClose(self, event):
self.Destroy()
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
class SecondaryFrame(wx.Frame):
def __init__(self, parent, title):
super().__init__(parent)
self.Title = title
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Center()
self.Show()
def OnClose(self, event):
self.Destroy()
if __name__ == '__main__':
wx_app = wx.App()
frame = MainFrame("Close me to exit")
wx_app.MainLoop()
Upvotes: 2