在pyqt中清理小部件的正确方法

时间:2012-12-11 20:15:48

标签: pyqt pyqt4

使用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做同样的事情吗?

1 个答案:

答案 0 :(得分:16)

您应该记住的第一件事是为您的小部件使用父/子关系。执行此操作时,它们将归Qt所有,并在删除父项时自动清理所有子项。

dialog = MyDialog()

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

在这种情况下,删除对话框时将正确清除所有复选框。这处理了你问题的一部分。我意识到当你将它们添加到布局时,你隐含地设置了父集。但是你不应该在删除之前清除那个父母。 允许自动删除子项的父关系。不是引用计数。参考方面将是一个python端的东西,当没有更多的引用时它将收集垃圾。

deleteLater非常重要,当您希望在控件返回到eventloop时发生删除时使用。当您从布局中删除窗口小部件并添加新窗口小部件时,它也是删除窗口小部件的安全方法:

# 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意味着删除它们。