2012-12-11 10 views
6

Was ist der 'richtige' oder idiomatische Weg, Widgets zu bereinigen/zu löschen, wenn PyQt4 verwendet wird?Richtiger Weg, um Widgets in pyqt zu bereinigen

Betrachten Sie den folgenden Code ein:

choices = ['a', 'b', 'c'] 
checkboxes = [] 
layout = QtGui.QVBoxLayout() 

dialog = MyDialog() 

for c in choices: 
    checkboxes.append(QtGui.QCheckBox(c) 
    layout.addWidget(chkbox) 

dialog.setLayout(layout) 

for c in checkboxes: 
    c.setParent(None) 
    c.deleteLater() 
    c = None 

Der obige Code verwendet setParent(), deleteLater() und Einstellen des Objekts None. Sind all diese Dinge notwendig?

Ein anderes mögliches Szenario ist, ich habe einen Dialog mit einer Reihe von Widgets darauf und möchte diese Widgets entfernen und neue hinzufügen. Ich möchte die alten Widgets nicht "auslecken", aber ich bin mir nicht sicher, was der richtige Weg wäre, um so etwas zu tun.

Es scheint mir, dass deleteLater() möglicherweise nie benötigt wird. Verringert es nur die Referenzzählung? Wenn ja, würde nicht nur die Variable auf "None" setzen?

Antwort

15

Als erstes sollten Sie daran denken, die Eltern/Kind-Beziehungen für Ihre Widgets zu verwenden. Wenn Sie dies tun, gehören sie Qt und werden automatisch alle Kinder bereinigen, wenn der Elternteil gelöscht wird.

dialog = MyDialog() 

for c in choices: 
    checkboxes.append(QtGui.QCheckBox(c, parent=dialog)) 
    layout.addWidget(chkbox) 

In diesem Fall werden alle Kontrollkästchen beim Löschen des Dialogfelds ordnungsgemäß bereinigt. Dies behandelt einen Teil Ihrer Frage. Ich stelle fest, dass Sie implizit die Eltern festgelegt haben, wenn Sie sie dem Layout hinzufügen. Sie sollten das übergeordnete Element jedoch nicht löschen, bevor Sie es löschen. Es ist die übergeordnete Beziehung, die das Kind automatisch entfernt werden kann. Keine Referenzzählung. Der Referenzaspekt wäre eine python-seitige Sache, bei der Müll gesammelt wird, wenn es keine Referenzen mehr darauf gibt.

deleteLater ist sehr wichtig, wenn Sie möchten, dass der Löschvorgang ausgeführt wird, wenn die Steuerung zum Eventloop zurückkehrt. Es ist auch der sichere Weg Widgets zu löschen, wenn Sie einige aus einem Layout und neue hinzufügen zu entferne:

# clear a layout and delete all widgets 
# aLayout is some QLayout for instance 
while aLayout.count(): 
    item = aLayout.takeAt(0) 
    item.widget().deleteLater() 

Diese Widgets tatsächlich gelöscht werden, wenn dieses Verfahren abgeschlossen ist. deleteLater ist auch nützlich, um das Widget zu löschen, unter dem der Slot oder das Ereignis gerade stattfindet. Wie ein QPushButton, der sich beim Klick selbst löschen kann.

Es gibt auch nicht viel zu setzen c = None. Sobald ein Elternteil gelöscht ist und die Löschung aller untergeordneten Elemente rekursiv ausgelöst wird, sind die Python-Verweise auf dieses Objekt ungültig. Alles, was Sie tun müssen, ist, sie einfach nicht mehr zu benutzen. Wenn sie sich in einer Liste befinden, löschen Sie die Liste. Der Zugriff auf sie würde die RuntimeError: wrapped C/C++ object of %S has been deleted Bedeutung bedeuten sie sind gelöscht.

+0

Ist es notwendig, das Argument 'parent' beim Erstellen aller Objekte zu verwenden, die einem Layout hinzugefügt werden? Ich weiß, das ist wahrscheinlich ein bisschen expliziter, aber ist es erforderlich? –

+0

Nein, nicht wirklich. Wenn Sie sie direkt zum Layout hinzufügen, werden sie durch das Layout zum Eigentümer des Layouts. – jdi

+0

Sehr spät zur Party, aber ich dachte, ich würde hinzufügen, dass - obwohl es nicht notwendig ist, das Argument "Eltern" zu verwenden - es ist wahrscheinlich eine gute Idee, da es die Struktur Ihres Codes ein wenig einschränkt, und es für andere einfacher macht um zu sehen, was die beabsichtigte Eindämmungshierarchie ist. – Emmet

Verwandte Themen