在wxPython中切换帧时出现wx._core.PyDeadObjectError?

1 投票
2 回答
528 浏览
提问于 2025-04-18 15:59

我在使用 wx.ComboBox 切换页面时遇到了问题。每当我切换页面超过两次时,就会出现错误。这对我来说是个大问题,我找不到解决办法。代码如下:

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

提前谢谢大家,我很期待看到你们的回答!

2 个回答

1

正如@wnnmaw已经很清楚地解释过的,你遇到的问题是因为你只部分地销毁了你的对象。

我简化了你的代码:

for i in ok:
    i.Destroy()

变成了(编辑,最简单的方法就是这样

for _ in ok:
    el = ok.pop()
    el.Destroy()

在一个操作中同时销毁这个元素并把它从列表中移除。

1

你遇到错误的原因是因为你把ok里的对象给杀掉了,但却没有把它们从列表中真正移除。这是个问题,因为这样一来,你的程序里就会有一些“死掉的”控件在那儿漂浮着。下面是你在处理addition时,列表的迭代过程:

第一次:

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

第二次:

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>]

第三次:

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

当Python遍历Ok并试图对那些“死掉的”控件应用Destroy时,就会出错,因为这个对象已经被杀掉了。杀掉这个对象并不会把它从列表中移除

我让你的代码正常工作的方法是,在添加新对象之前先重置ok不过,我需要把ok设为一个类的属性。下面是带有调试打印语句的工作代码:

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

撰写回答