使用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做同样的事情吗?
答案 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
意味着删除它们。