8

PyQt4を使用するときにウィジェットをクリーンアップ/削除する「正しい」または慣用的な方法は何ですか?

次のコードを検討してください。

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

上記のコードではsetParent()、を使用しdeleteLater()、オブジェクトを に設定していますNone。これらはすべて必要ですか?

別の考えられるシナリオは、多数のウィジェットを含むダイアログがあり、これらのウィジェットを削除して新しいウィジェットを追加したいというものです。古いウィジェットを「リーク」したくはありませんが、このようなことを行う正しい方法が何であるかはわかりません。

それは決して必要とされないかもしれないと私には思えdeleteLater()ます。参照カウントを減らすだけですか?もしそうなら、変数を None に設定するだけで同じことはできませんか?

4

1 に答える 1

18

最初に覚えておくべきことは、ウィジェットの親子関係を使用することです。これを行うと、それらは Qt によって所有され、親が削除されるとすべての子が自動的にクリーンアップされます。

dialog = MyDialog()

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

この状況では、ダイアログを削除すると、すべてのチェックボックスが適切にクリーンアップされます。これは、質問の一部を処理します。レイアウトに追加すると、暗黙的に親が設定されていることがわかります。ただし、削除する前にその親をクリアしないでください。子を自動的に削除できるのは、親の関係です。参照カウントではありません。参照の側面は、それへの参照がなくなったときにガベージコレクションを取得するPython側のものになります。

deleteLater制御がイベントループに戻ったときに削除を実行する場合に使用するために、非常に重要です。また、レイアウトから一部を削除して新しいウィジェットを追加するときに、ウィジェットを安全に削除する方法でもあります。

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

これらのウィジェットは、このメソッドが完了すると実際に削除されます。deleteLaterスロットまたはイベントが現在発生しているウィジェットを削除する場合にも役立ちます。クリックすると自分自身を削除できる QPushButton など。

設定する必要もあまりありませんc = None。親が削除され、そのすべての子が再帰的に削除されると、そのオブジェクトへの Python 参照は無効になります。したがって、あなたがする必要があるのは、それらをもう使用しないことだけです. それらがリストにある場合は、リストをクリアします。それらにアクセスすると、RuntimeError: wrapped C/C++ object of %S has been deletedそれらが削除されたという意味が生じます。

于 2012-12-11T22:30:26.873 に答える