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 回答