如何在用户单击框架关闭时终止WxPython应用程序

Jes*_*ose 15 python wxpython

当我单击主框架的关闭按钮时,应用程序应该关闭.但是我实现它的方式,Segmentation fault当我点击按钮时,它会退出.

我担心安全关闭程序,因为我需要稍后将内容保存到磁盘.

通过关闭按钮终止WxPython应用程序的正确非暴力方法是什么?


这是我实现的程序的"主要"循环:

if __name__ == "__main__":
    app = wx.App(False)
    mf = MainFrame(None, title='Spectrum Checker') #subclasses frame
    mf.register_close_callback( app.Destroy) #what is the apt func?
    app.MainLoop()
Run Code Online (Sandbox Code Playgroud)

以下是如何在以下内容中实现回调MainFrame:

def __init__(self, parent, title):
    ...
    self.Bind(wx.EVT_CLOSE, self._when_closed)

...

def _when_closed(self, event):
if self.__close_callback__:
    self.__close_callback__()
Run Code Online (Sandbox Code Playgroud)

Mik*_*oll 13

这是关闭框架的常规方法:

import wx

########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Close Me")
        panel = wx.Panel(self)

        closeBtn = wx.Button(panel, label="Close")
        closeBtn.Bind(wx.EVT_BUTTON, self.onClose)

    #----------------------------------------------------------------------
    def onClose(self, event):
        """"""
        self.Close()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    frame.Show()
    app.MainLoop()
Run Code Online (Sandbox Code Playgroud)

现在,如果你有一个绑定到wx.EVT_CLOSE,那么你将进入一个无限循环,直到你得到一个段错误.绑定到EVT_CLOSE的主要原因是您可以捕获close事件并要求用户保存其信息.如果你想这样做,那么你需要使用self.Destroy而不是"self.Close",所以你不要继续发射该事件.

正如已经提到的,在你的关闭处理程序中,你需要确保你结束线程,销毁任务栏图标,关闭打开的文件等,所以没有任何东西挂起.另见:http://wxpython.org/docs/api/wx.CloseEvent-class.html


OP的补充

我面临两个问题,我感谢所有三个答案,帮助我找到它们:

首先,框架没有响应,self.Close()或者self.Destroy()因为它具有一个self.stuff具有正在运行的线程的属性.必须先关闭此线程.

第二,self.Close()在处理程序中,响应close事件并在调用时导致无限递归.这会导致运行时错误(分段错误,超出递归深度).解决方案是使用self.Destroy().


uhz*_*uhz 6

我不确定为什么你需要回调来关闭应用程序?如果未绑定任何内容MainFrame,则单击关闭按钮时应自动关闭应用程序.除非你有一些其他线程运行阻止进程结束.如果您仍希望绑定到close事件并在关闭之前执行某些操作,则应event.Skip()在事件处理程序中使用,如果您仍想关闭窗口.否则,事件不会进一步传播,并且不会执行默认处理程序.一个例子:

import wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.__close_callback = None
        self.Bind(wx.EVT_CLOSE, self._when_closed)

    def register_close_callback(self, callback):
        self.__close_callback = callback

    def _when_closed(self, event):
        doClose = True if not self.__close_callback else self.__close_callback()
        if doClose:
            event.Skip()

if __name__ == "__main__":
    app = wx.App(False)
    mf = MainFrame(None, title='Test')
    mf.Show()
    mf.register_close_callback(lambda: True)
    app.MainLoop()
Run Code Online (Sandbox Code Playgroud)

执行代码并单击关闭时 - 应用程序将关闭.当您将回调函数更改lambda: False为窗口时,将不会关闭,因为Skip未调用.