同时删除小部件和布局

时间:2012-02-21 08:04:13

标签: python layout pyqt pyqt4

我试图找到一些需要qt布局的东西并从中删除所有内容。想象一下窗口的样子 - 我有:

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

所以我需要一些东西,我可以递归地调用CLEAR AND DELETE来自我的父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()

2 个答案:

答案 0 :(得分:13)

清除布局最安全的方法是使用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())

答案 1 :(得分:7)

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

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

永远不会是True,您将尝试.widget() QLayoutItem并返回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)