从布局中删除所有项目

Posted

技术标签:

【中文标题】从布局中删除所有项目【英文标题】:Remove all items from a layout 【发布时间】:2012-02-21 08:04:12 【问题描述】:

我试图找到可以采用 qt 布局并从中删除所有内容的东西。只是想象一下窗口的样子 - 我有:

QVBoxLayout
     | ------QHboxLayout
                 |---------QWidget
     | ------QHboxLayout
                 |---------QWidget
            .........

所以我需要一些可以递归调用的东西来清除和删除我父母 QVBoxLayout 的所有东西。我尝试了这里提到的东西(Clear all widgets in a layout in pyqt),但它们都不起作用(无论如何都没有标记正确的答案)。我的代码如下所示:

def clearLayout(self, layout):
    for i in range(layout.count()):
        if (type(layout.itemAt(i)) == QtGui.QHBoxLayout):
            print "layout " + str(layout.itemAt(i))
            self.clearLayout(layout.itemAt(i))
        else:
            print "widget" + str(layout.itemAt(i))
            layout.itemAt(i).widget().close()

但它给出了一个错误:

               layout.itemAt(i).widget().close()
            AttributeError: 'NoneType' object has no attribute 'close'

=>编辑 这有点工作(但如果有任何其他Layout 而不是HBoxLayout

def clearLayout(self, layout):
    layouts = []
    for i in range(layout.count()):
        if (type(layout.itemAt(i)) == QtGui.QHBoxLayout):
            print "layout " + str(layout.itemAt(i))
            self.clearLayout(layout.itemAt(i))
            layouts.append(layout.itemAt(i))
        else:
            print "widget" + str(layout.itemAt(i))
            if (type(layout.itemAt(i)) == QtGui.QWidgetItem):
                layout.itemAt(i).widget().close()

【问题讨论】:

【参考方案1】:

清除布局最安全的方法是使用 takeAt 方法提取项目,然后使用 deleteLater 显式删除任何小部件:

def clearLayout(self, layout):
    if layout is not None:
        while layout.count():
            item = layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            else:
                self.clearLayout(item.layout())

【讨论】:

这是一个更优雅的解决方案。谢谢【参考方案2】:

您的代码的问题是 QLayout.itemAt() 返回 QLayoutItemQWidgetItemQSpacerItem,具体取决于该位置的项目。所以条件:

type(layout.itemAt(i)) == QtGui.QHBoxLayout

永远不会是True,您将尝试为QLayoutItem 执行.widget() 并返回None。因此你得到的错误。另一件事是,您需要向后循环。因为从一开始就删除东西会改变项目并改变项目的顺序。

你需要这样写你的函数:

def clearLayout(self, layout):
    for i in reversed(range(layout.count())):
        item = layout.itemAt(i)

        if isinstance(item, QtGui.QWidgetItem):
            print "widget" + str(item)
            item.widget().close()
            # or
            # item.widget().setParent(None)
        elif isinstance(item, QtGui.QSpacerItem):
            print "spacer " + str(item)
            # no need to do extra stuff
        else:
            print "layout " + str(item)
            self.clearLayout(item.layout())

        # remove the item from layout
        layout.removeItem(item)    

【讨论】:

几乎在那里但不完全 :) 无论如何谢谢 :) 当我运行您提供的功能时,您提供的所有 QHboxLayouts 都被归类为垫片。由于这不是真的“根据该位置的项目返回 QLayoutItem、QWidgetItem 或 QSpacerItem。” => 我的 itemAt 返回不是 QLayoutItem 的 QHboxLayout 我将其修复如下: def clearLayout(self, layout): for i in range(layout.count()): if (type(layout.itemAt(i)) == QtGui. QHBoxLayout): 打印 "layout" + str(layout.itemAt(i)) self.clearLayout(layout.itemAt(i)) else: print "widget" + str(layout.itemAt(i)) if (type(layout. itemAt(i)) == QtGui.QWidgetItem): layout.itemAt(i).widget().close() @user965847:这很奇怪。我得到QLayoutItems 的试用版。无论如何,我编辑了代码。试试这个。

以上是关于从布局中删除所有项目的主要内容,如果未能解决你的问题,请参考以下文章

删除 ListView 中所有项目的 onClick 突出显示

在列表视图项目中使用折叠不会完全删除特定项目视图的空间

Qt 5.5 使用 C++,从 ComboBox 中删除和项目正在删除项目之前的所有项目

从 Visual Studio 项目中的项目中删除所有未使用的引用

从全局环境中删除除几个项目之外的所有项目

使用自动布局查找笔尖