2011-11-02 52 views
4

使用下面的代码,我的预览小部件的__del__方法永远不会被调用。如果我取消注释“del window”这一行,它就行。为什么?未使用父窗口删除QWidget

#!/usr/bin/env python 

from PyQt4 import QtGui 

class Preview(QtGui.QWidget): 
    def __init__(self, parent): 
    QtGui.QWidget.__init__(self, parent) 

    def __del__(self): 
    print("Deleting Preview") 

class PreviewWindow(QtGui.QMainWindow): 
    def __init__(self): 
    QtGui.QMainWindow.__init__(self) 

    self.widget = Preview(self) 
    self.setCentralWidget(self.widget) 

    def __del__(self): 
    print("Deleting PreviewWindow") 

if __name__ == "__main__": 
    app = QtGui.QApplication(["Dimension Preview"]) 
    window = PreviewWindow() 
    window.show() 
    app.exec() 
    # del window 
+0

它为我在Fedora的Linux 14(PyQt的4.8.3,Python 2.7版) 。不过,我不得不将app.exec()更改为app.exec_()。 – xioxox

+0

@xioxox。你确定_both_'__del__'方法被调用吗? – ekhumoro

+0

是的 - 他们为我做的 – xioxox

回答

2

如果QObject子类具有父,那么Qt的将它删除当父被删除。另一方面,如果一个QObject子类没有父节点,它将(最终)被python删除。

希望这个例子可以让事情变得更为清楚:

from PyQt4 import QtGui 

class Widget(QtGui.QWidget): 
    def __init__(self, parent): 
     QtGui.QWidget.__init__(self, parent) 
     self.destroyed.connect(self.handleDestroyed) 

    def __del__(self): 
     print ('__del__:', self) 

    def handleDestroyed(self, source): 
     print ('destroyed:', source) 

class Foo(Widget): 
    def __init__(self, parent): 
     Widget.__init__(self, parent) 

class Bar(Widget): 
    def __init__(self, parent): 
     Widget.__init__(self, parent) 

class Window(Widget): 
    def __init__(self, parent=None): 
     Widget.__init__(self, parent) 
     self.foo = Foo(self) 
     self.bar = Bar(None) 

if __name__ == "__main__": 

    app = QtGui.QApplication([__file__, '-widgetcount']) 
    window = Window() 
    window.show() 
    app.exec_() 

,输出:

__del__: <__main__.Window object at 0x88f514c> 
destroyed: <__main__.Foo object at 0x88f5194> 
__del__: <__main__.Bar object at 0x88f51dc> 
Widgets left: 0 Max widgets: 4 

编辑

退一步来说,似乎有可能是一个错误(或至少在行为上有所不同)与某些版本的PyQt4。

作为一种可能的解决方法,似乎为主小部件创建两个python名称,然后明确删除它们中的每一个都可能有助于确保对象的C++和python两端都被销毁。

如果下面的行被添加到上面的脚本:

tmp = window; del tmp, window 

然后输出变为:

__del__: <__main__.Window object at 0x8d3a14c> 
__del__: <__main__.Foo object at 0x8d3a194> 
__del__: <__main__.Bar object at 0x8d3a1dc> 
Widgets left: 0 Max widgets: 4 
+0

因此''__del__'永远不会被调用是在那种情况下的预期行为?这导致我的应用程序泄漏。如果你使用'self.setCentralWidget(self.widget)',那么使用'parent = None'不会有帮助。 –

+0

@TavianBarnes。我编辑了我的答案,并为您的问题添加了可能的解决方案。 – ekhumoro

+1

好的,谢谢!对于错误追踪我去。 –