wxPython wx.Close 创建运行时错误

0 投票
3 回答
2540 浏览
提问于 2025-04-16 02:12

当我在顶层框架的 EVT_CLOSE 事件处理函数中尝试调用 self.Close(True) 时,出现了一个运行时错误:最大递归深度超出。以下是代码:

from PicEvolve import PicEvolve
import wx

class PicEvolveFrame(wx.Frame):

    def __init__(self, parent, id=-1,title="",pos=wx.DefaultPosition,
         size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
         name="frame"):

        wx.Frame.__init__(self,parent,id,title,pos,size,style,name)

        self.panel = wx.ScrolledWindow(self)
        self.panel.SetScrollbars(1,1,600,400)

        statusBar = self.CreateStatusBar()

        menuBar = wx.MenuBar()
        menu1 = wx.Menu()
        m = menu1.Append(wx.NewId(), "&Initialize", "Initialize population with random images")
        menuBar.Append(menu1,"&Tools")
        self.Bind(wx.EVT_MENU,self.OnInit,m)
        self.Bind(wx.EVT_CLOSE,self.OnClose)

        self.SetMenuBar(menuBar)

    def OnInit(self, event):

        dlg = wx.TextEntryDialog(None,"Enter Population Size:","Population Size")
        popSize = 0
        if dlg.ShowModal() == wx.ID_OK:
            popSize = int(dlg.GetValue())
            self.pEvolver = PicEvolve(popSize,(200,200),True)

        box = wx.BoxSizer(wx.VERTICAL)

        filenames = []
        for i in range(popSize):
            filenames.append("img"+str(i)+".png")
        for fn in filenames:
            img = wx.Image(fn,wx.BITMAP_TYPE_ANY)
            box.Add(wx.StaticBitmap(self.panel,wx.ID_ANY,wx.BitmapFromImage(img)), 0,wx.BOTTOM)

        self.panel.SetSizer(box)

    def OnClose(self,event):

        self.Close(True)

class PicEvolveApp(wx.App):

    def OnInit(self):

        self.frame = PicEvolveFrame(parent=None,title="PicEvolve")
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

if __name__ == "__main__":

    app = PicEvolveApp()
    app.MainLoop() 

3 个回答

0

你不需要处理 EVT_CLOSE,除非你想做一些特别的事情,比如提示用户保存。如果你想这样做,那就用 self.Destroy()。现在你点击右上角的“x”时,会调用 OnClose,然后再调用 Close,这样就会触发 OnClose 事件……这就是你出现递归错误的原因。

如果你不处理 EVT_CLOSE,直接用 self.Close() 应该是可以的。如果不行,那通常意味着你有一个定时器、线程或者某个隐藏的窗口需要被停止或关闭。我希望这样解释能让你明白。

0
def OnClose(self,event):
   event.Skip()

请查看这个链接:http://wiki.wxpython.org/EventPropagation

1

当你调用 window.Close 时,会触发 EVT_CLOSE 事件。

EVT_CLOSE 的处理函数会在用户尝试通过窗口管理器的控件或系统菜单关闭一个窗口或对话框时被调用。这个事件也可以通过程序本身来触发,比如调用 wx.Window.Close 函数。

所以很明显,这样会导致一个无限递归循环。相反,在 EVT_CLOSE 的处理函数中,你可以选择销毁窗口

def OnClose(self,event):
    self.Destroy()

或者跳过这个事件

def OnClose(self,event):
    event.Skip(True)

或者根本不处理 EVT_CLOSE 事件。

补充说明:

顺便问一下,为什么你想要处理这个事件?在其他问题中你有提到一些评论,建议你更新一下问题,这样大家才能给出更好的答案。

例如,当你的程序在关闭后仍然在命令提示符下等待时,这可能意味着你还有某个顶层窗口没有关闭。

要调试哪个窗口还开着,可以试试这个

for w in wx.GetTopLevelWindows():
    print w

撰写回答