Da es in Python bereits einen Garbage Collector gibt, ist deleteLater() in PyQt/PySide notwendig?Ist deleteLater() in PyQt/PySide notwendig?
Antwort
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 .
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.
- 1. PyQt4 setParent vs deleteLater
- 2. Ist CDATA wirklich notwendig?
- 3. Ist os.path.join notwendig?
- 4. ist StructureMap HttpContextScoped notwendig?
- 5. Ist die Verzeichnistrennkonstante notwendig?
- 6. Ist "Selbst" notwendig?
- 7. Ist ExecutePendingTransactions() immer notwendig?
- 8. Wann ist Backtracking notwendig?
- 9. Ist dieser Interrupt() notwendig?
- 10. Ist KillTimer notwendig?
- 11. Ist so viel Entkommen notwendig?
- 12. Ist der Ausdruck math.sqrt() notwendig?
- 13. Warum ist gwt-bootstrap notwendig?
- 14. Ist `std :: move 'hier notwendig?
- 15. jquery - Ist $ (Dokument) .ready notwendig?
- 16. Ist `webdriver-manager start` notwendig?
- 17. Ist eine konstante Abfrage in RXTX notwendig?
- 18. Ist registerNamespace in DOMXPath von PHP notwendig?
- 19. Ist ein $ -Ereignis notwendig in ng-click
- 20. Warum ist Typhinweis in PHP notwendig?
- 21. Python: Ist in diesem Fall isinstance() notwendig?
- 22. Ist in dieser Situation eine Sperre notwendig?
- 23. Ist Fragezeichen Operator ‚?‘ in Haxe wirklich notwendig?
- 24. ist Python Rückkehr immer notwendig
- 25. Ist es notwendig, sich abzumelden
- 26. Ist diese Pointer-Initialisierung notwendig?
- 27. Ist copy_to_user mit procfs notwendig?
- 28. ist es notwendig, sich von Veranstaltungen abzumelden?
- 29. Warum ist der Variablenname "$ scope" notwendig?
- 30. Wann ist die Reintegrationsoption wirklich notwendig?
danke für das erklären. – iMath
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
@ 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