Search code examples
pythonpython-2.7comboboxwxpython

wx._core.PyDeadObjectError when switching frames in wxPython?


I have I problem when switching between pages in my wx.ComboBox. The error seems to be when to change pages more then twice. This is a huge bug for me that I can't seem to find a solution for. Code:

import wx
ok=[]
class oranges(wx.Frame):

    def __init__(self,parent,id):
        wx.Frame.__init__(self,parent,id,'Testing Sample',size=(1024,768))
        self.frame=wx.Panel(self)
        some_text=wx.StaticText(self.frame,-1,'TEXT',pos=(500,500))
        more_choices=['Home','Page One']
        self.adding=wx.ComboBox(self.frame,choices=more_choices,pos=(300,722),style=wx.CB_READONLY)
        self.Bind(wx.EVT_COMBOBOX,self.addition,self.adding)
    def addition(self,event):
        if self.adding.GetValue()=='Home':
            for i in ok:
                i.Destroy()
            ok.append(wx.StaticText(self.frame,-1,'Oranges',pos=(300,300)))
        elif self.adding.GetValue()=='Page One':
            for i in ok:
                i.Destroy()
            ok.append(wx.StaticText(self.frame,-1,'Apples',pos=(300,300)))
        else: pass
if __name__ =='__main__':
    app = wx.PySimpleApp()
    window = oranges(parent=None,id=-1)
    window.Show()
    app.MainLoop()

Thanks in advance and I can't wait to see the answers!


Solution

  • The reason you get your error is because you kill the objects in ok but don't actually remove them from the list. That's bad since you then have dead husks of widgets floating around in your program. Here's how your iteration of the list looks as you go through each line of addition:

    First Time:

    for i in ok:                                                      #[]
        i.Destroy()                                                   #[]
    ok.append(wx.StaticText(self.frame,-1,'Oranges',pos=(300,300)))   #[<wx object with oranges>]
    

    Second Time:

    for i in ok:                                                      #[<wx object with oranges>]
        i.Destroy()                                                   #[<wx object with oranges>]]
    ok.append(wx.StaticText(self.frame,-1,'Oranges',pos=(300,300)))   #[<dead husk>, <wx object with apples>]
    

    Third Time:

    for i in ok:                                                      #[<dead husk>, <wx object with apples>]
        i.Destroy()                                                   #[<dead husk>, <wx object with apples>]
    

    When Python loops over Ok and tries to apply Destroy to the dead husk, it breaks since the object has been killed. Killing this object does not remove it from the list.

    I got your code to work by resetting ok before the new object is appended. However, I had to make ok a class attribute. Working code below with diagnostic print statements:

    import wx
    class oranges(wx.Frame):
        ok=[]
    
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,'Testing Sample',size=(1024,768))
            self.frame=wx.Panel(self)
            some_text=wx.StaticText(self.frame,-1,'TEXT',pos=(500,500))
            more_choices=['Home','Page One']
            self.adding=wx.ComboBox(self.frame,choices=more_choices,pos=(300,722),style=wx.CB_READONLY)
            self.Bind(wx.EVT_COMBOBOX,self.addition,self.adding)
        def addition(self,event):
            if self.adding.GetValue()=='Home':
                print "1 ", self.ok
                for i in self.ok:
                    i.Destroy()
                self.ok = []
                self.ok.append(wx.StaticText(self.frame,-1,'Oranges',pos=(300,300)))
                print "2 ", self.ok
            elif self.adding.GetValue()=='Page One':
                print "3 ", self.ok
                for i in self.ok:
                    i.Destroy()
                self.ok = []
                self.ok.append(wx.StaticText(self.frame,-1,'Apples',pos=(300,300)))
                print "4 ", self.ok
            else: pass
    if __name__ =='__main__':
        app = wx.PySimpleApp()
        window = oranges(parent=None,id=-1)
        window.Show()
        app.MainLoop()