在pyqt中清除布局中的所有控件

65 投票
14 回答
116144 浏览
提问于 2025-04-16 09:00

有没有办法清空(删除)布局中的所有小部件?

self.plot_layout = QtGui.QGridLayout()
self.plot_layout.setGeometry(QtCore.QRect(200,200,200,200))
self.root_layout.addLayout(self.plot_layout)
self.plot_layout.addWidget(MyWidget())

现在我想用一个新的小部件替换掉plot_layout中的小部件。有没有简单的方法可以清除plot_layout中的所有小部件?我没有找到这样的办法。

14 个回答

30

PALEN的回答在你不需要往布局里添加新控件的时候效果很好。

for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().setParent(None)

但是,如果你多次清空和填充布局,或者添加很多控件,就会出现“段错误(核心已转储)”的问题。看起来这个布局会保持一个控件的列表,而这个列表的大小是有限制的。

如果你按照下面的方式移除控件:

for i in reversed(range(layout.count())): 
    widgetToRemove = layout.itemAt(i).widget()
    # remove it from the layout list
    layout.removeWidget(widgetToRemove)
    # remove it from the gui
    widgetToRemove.setParent(None)

你就不会遇到这个问题了。

42

这可能有点晚了,但我想为将来参考补充一下:

def clearLayout(layout):
  while layout.count():
    child = layout.takeAt(0)
    if child.widget():
      child.widget().deleteLater()

这段内容是从Qt文档中改编的,链接在这里:http://doc.qt.io/qt-5/qlayout.html#takeAt。记住,当你在一个循环(比如while或for循环)中从布局中移除子项时,实际上是在改变每个子项在布局中的索引编号。这就是为什么使用for i in range()循环时会遇到问题的原因。

136

经过大量的研究(这花了我不少时间,所以我把它记录下来以备将来参考),我找到了一种真正清除和删除布局中小部件的方法:

for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().setParent(None)

文档中关于QWidget的说明是:

当父级被删除时,新小部件也会被删除。

重要提示:你需要反向循环,因为从开头删除东西会导致其他项目的位置发生变化,从而改变布局中项目的顺序。

要测试并确认布局是否为空:

for i in range(layout.count()): print i

似乎还有另一种方法可以做到这一点。与其使用setParent函数,不如使用deleteLater()函数,像这样:

for i in reversed(range(layout.count())): 
    layout.itemAt(i).widget().deleteLater()

文档中提到QObject.deleteLater (self)

将这个对象安排为待删除。

然而,如果你运行上面指定的测试代码,它会打印出一些值。这表明布局中仍然有项目,而不是使用setParent的代码。

撰写回答