退出具有多个 windows 的 wxPython 应用程序

Exiting a wxPython application with multiple windows

我的 wxPython 应用程序由一个主 window 和用户可以选择启动的任意数量的辅助 windows 组成。当用户关闭主 window 时,我希望应用程序退出(当然,所有其他 windows 也关闭)。 标准行为是应用程序仅在用户关闭最后一个 window.

时退出

我是否需要编写所有 windows 的全局列表,只是为了迭代并关闭它们以退出应用程序? 我想要的 GUI 行为真的非常不标准以至于需要自定义代码来实现吗?我期待一个简单的 App.exit() 调用或类似的调用。

编辑:我现在找到了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.

但它对我不起作用。

这是一个简短的例子。关闭 frame1 应该退出应用程序,但它没有。有必要同时关闭 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()

问题是您有 2 个顶级框架。
App 在最后一个顶级框架关闭时关闭,因此通常有 1 个顶级框架,后续框架将其作为 parent
通过这种安排,当父框架关闭时,子框架也会关闭。
参见:https://docs.wxpython.org/app_overview.html#application-shutdown
或者参见:https://docs.wxpython.org/wx.functions.html#wx.Exit

以你的例子为例:

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()