2010-08-02 55 views
0

当我尝试在顶层Frame的EVT_CLOSE事件处理函数中调用self.Close(True)时,它会引发RuntimeError:超出最大递归深度。下面的代码:wxPython wx.Close创建运行时错误

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

回答

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

看到http://wiki.wxpython.org/EventPropagation

+1

顺便说一句,靠近已经被称为当您关闭在框架上,所以这个回调是没有必要的,除非你想期间_do_东西它。 – iondiode 2010-08-02 20:04:34

+0

嗯..我试着添加Skip(),它仍然返回相同的错误。我把回调放在那里的原因是,当我尝试退出时,窗口关闭,但程序仍在提示符下运行。 – Johnny 2010-08-02 20:48:55

+0

是的,这是因为我把它放在那里仍然是错误的(doh)。实际上,如果我注释掉导入的PicEvolve行,并删除绑定onclose和onClose回调,此代码工作正常。因此,也许在picEvolve模块中的某些内容正在运行init – iondiode 2010-08-03 22:50:56

0

,除非你想要做一些特别的东西,比如提示用户保存你不需要EVT_CLOSE赶上。如果你这样做,然后调用self.Destroy()。现在,当你点击右上角的“x”,然后调用“Close”,它会触发OnClose事件时,调用OnClose ....这就是为什么会出现递归错误。

如果你没有捕获EVT_CLOSE并使用self.Close()它应该工作。如果没有,那通常意味着你有一个计时器,线程或隐藏的顶级窗口,这些窗口也需要停止或关闭。我希望这是有道理的。

+0

如何判断是否有其他需要关闭的运行?也许我的PicEvolve类(用来制作放在面板中的图片)的东西挂起来了 - 我会如何告诉wxPython停止它? – Johnny 2010-08-02 21:21:49

+0

如果你有定时器运行,那么在你的OnClose事件中,你需要停止它们。您可以使用计时器的IsRunning()方法来检查它们。对于顶层窗口,使用wx.GetTopLevelWindows()获取所有这些列表,然后遍历它们,根据需要关闭或销毁它们。 – 2010-08-02 22:53:27

1

当您调用window.Close时,它会触发EVT_CLOSE。 从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 a a 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.

引用所以很明显,你将进入一个无限递归循环。相反,在EVT_CLOSE的处理或者销毁窗口

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

或跳过事件

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

或不赶EVT_CLOSE。

编辑: 顺便说一句,为什么你要捕捉事件,在其他问题,你已经提出了一些意见,你应该相应地更新问题,以便人们可以给出更好的答案。

例如,当程序在关闭后仍然等待命令提示符时,可能意味着您的顶级窗口仍然未关闭。

要调试其中之一仍然是开放的,试试这个

for w in wx.GetTopLevelWindows(): 
    print w