2013-11-23 7 views

Antwort

12

Es hängt davon ab, was Sie mit "notwendig" meinen.

Eine Anwendung könnte potenziell viel Speicher verbrauchen, wenn (zum Beispiel) Vorsicht beim Schließen Widgets genommen wird. Die QObject-basierten Klassen sind (optional) in einer Hierarchie miteinander verknüpft. Wenn ein Objekt der obersten Ebene gelöscht wird, löscht Qt automatisch alle untergeordneten Objekte. Beim Schließen von Widgets (die Unterklassen von QObject sind) wird das automatische Löschen jedoch nur ausgeführt, wenn das Attribut Qt.WA_DeleteOnClose festgelegt ist (was normalerweise nicht der Fall ist).

Zur Veranschaulichung, versuche immer wieder öffnen und den Dialog in dieser Demo-Skript zu schließen, und beobachtet, wie die globale Liste der Objekte wächst:

from PyQt4 import QtCore, QtGui 

class Window(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 
     self.checkbox = QtGui.QCheckBox('Delete') 
     self.button = QtGui.QPushButton('Open', self) 
     self.button.clicked.connect(self.openDialog) 
     layout = QtGui.QHBoxLayout(self) 
     layout.addWidget(self.checkbox) 
     layout.addWidget(self.button) 

    def openDialog(self): 
     widget = QtGui.QDialog(self) 
     if (self.checkbox.isChecked() and 
      not widget.testAttribute(QtCore.Qt.WA_DeleteOnClose)): 
      widget.setAttribute(QtCore.Qt.WA_DeleteOnClose) 
      for child in self.findChildren(QtGui.QDialog): 
       if child is not widget: 
        child.deleteLater() 
     label = QtGui.QLabel(widget) 
     button = QtGui.QPushButton('Close', widget) 
     button.clicked.connect(widget.close) 
     layout = QtGui.QVBoxLayout(widget) 
     layout.addWidget(label) 
     layout.addWidget(button) 
     objects = self.findChildren(QtCore.QObject) 
     label.setText('Objects = %d' % len(objects)) 
     print(objects) 
     widget.show() 

if __name__ == '__main__': 

    import sys 
    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(500, 300, 100, 50) 
    window.show() 
    sys.exit(app.exec_()) 

Mit PyQt/pyside gibt zwei Aspekte sind Eigentum einzuwenden: die Python-Teil und der Qt-Teil. Häufig reicht es nicht aus, den letzten Python-Verweis auf ein Objekt zu entfernen, da auf der Qt-Seite immer noch ein Verweis vorhanden sein könnte.

Im Allgemeinen tendiert Qt nicht zu implicity löschen Objekte. Wenn also Ihre Anwendung viele QObjects erstellt und entfernt (oder viele QWidgets öffnet und schließt), müssen Sie möglicherweise Schritte unternehmen, um sie explizit zu löschen, wenn die Speicherbelegung ein Problem darstellt.

UPDATE:

nur auf die Punkte oben auf Objektbesitz hinzuzufügen. Manchmal ist es möglich, einen Python-Verweis auf ein Objekt zu halten, während der Qt-Teil gelöscht wird. Wenn dies geschieht, wird ein Fehler wie diese:

RuntimeError: underlying C/C++ object has been deleted

Üblicherweise wird die Qt-Dokumentation einige Hinweise darüber geben, wann dies passieren könnte. Zum Beispiel gibt QAbstractItemView.setModel diese Warnung:

The view does not take ownership of the model unless it is the model's parent object...

Dies werden Ihnen sagen, dass Sie entweder eine Python-Referenz auf das Objekt halten müssen, oder ein geeignetes übergeordnetes Objekt an den Konstruktor des Objekts übergeben, weil Qt wird nicht immer automatisch Reparent .

+0

danke für das erklären. – iMath

+1

1) Ich denke, es gibt keinen Unterschied in PyQt/PySide oder Python Teil, Solange das Objekt referenziert ist, wird es nicht aufgeräumt. Denken Sie nicht auch? 2) Außerdem ist WA_DeleteOnClose geeignet für Widget, dass wir es schließen können, aber für QOBject wie QNetworkReply und QDialog hier geschlossen, aber nicht gelöscht werden, deleteLater() ist geeignet, oder? – iMath

+0

@ user1485853. (1) Ja, aber sehen Sie die Aktualisierung meiner Antwort für eine wichtige Ausnahme. (2) Ja, 'WA_DeleteOnClose' ist nur _ein_ häufiges Beispiel dafür, wenn Dinge _might_ nicht richtig aufgeräumt werden.Für QOjects, wenn sie keinen Eltern- und keinen Python-Verweis haben, werden sie automatisch (schließlich) mit einem Garbage-Collected-Befehl versehen - so dass deleteLater() nicht benötigt wird. Sorgen Sie sich im Allgemeinen nicht zu sehr um das explizite Löschen von Objekten: Vorsicht vor "vorzeitiger Optimierung"! Sorgen Sie sich nur um diese Probleme, wenn Sie einen echten Beweis dafür haben, dass sie ein Problem verursachen. – ekhumoro

0

Eine Anwendung von deleteLater kann das Aufräumen von Ihnen selbst sein, d. H. Das Planen eines Löschens eines QObject (zum Beispiel im Threading), um Ressourcen innerhalb des Objekts selbst freizugeben.

Hier für example jemand verwendet es in Verbindung mit dem Signal thread.fulled. Es könnte jedoch auf Fälle mit starker Signalisierung beschränkt sein.