2011-11-02 49 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

好的,謝謝!對於錯誤追蹤我去。 –