简体   繁体   中英

wxPython wx.Close create runtime error

When I try to call self.Close(True) in the top level Frame's EVT_CLOSE event handler, it raises a RuntimeError: maximum recursion depth exceeded. Here's the code:

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

When you call window.Close it triggers EVT_CLOSE. Quoted from http://www.wxpython.org/docs/api/wx.CloseEvent-class.html

The handler function for EVT_CLOSE is called when the user has tried to close aa frame or dialog box using the window manager controls or the system menu. It can also be invoked by the application itself programmatically, for example by calling the wx.Window.Close function.

so obviously you will go into a infinite recursive loop. Instead in handler of EVT_CLOSE either destroy the window

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

or Skip the event

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

or do not catch the EVT_CLOSE.

Edit: Btw why you want to catch the event, in other question you have put some comment, you should update the question accordingly, so that people can give better answers.

eg when your program is still waiting on command prompt after close, it may mean you have some top level window still not closed.

To debug which one is still open, try this

for w in wx.GetTopLevelWindows():
    print w
def OnClose(self,event):
   event.Skip()

see http://wiki.wxpython.org/EventPropagation

You don't need to catch EVT_CLOSE unless you want to do something special, like prompt the user to save. If you do that sort of thing, then call self.Destroy() instead. Right now you call OnClose when you hit the upper right "x", which then calls "Close", which fires the OnClose event....that's why you get the recursion error.

If you don't catch EVT_CLOSE and use self.Close() it should work. When it doesn't, then that usually means you have a timer, thread or hidden top-level window somewhere that also needs to be stopped or closed. I hope that made sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM