同时删除小部件和布局

kos*_*ta5 3 python layout pyqt pyqt4

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

QVBoxLayout
     | ------QHboxLayout
                 |---------QWidget
     | ------QHboxLayout
                 |---------QWidget
            .........
Run Code Online (Sandbox Code Playgroud)

所以我需要一些东西,我可以递归地调用CLEAR AND DELETE来自我父母的所有东西QVBoxLayout.我尝试了这里提到的东西(清除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()
Run Code Online (Sandbox Code Playgroud)

但它给出了一个错误:

               layout.itemAt(i).widget().close()
            AttributeError: 'NoneType' object has no attribute 'close'
Run Code Online (Sandbox Code Playgroud)

=>编辑这种方法有效(但如果除了以下情况之外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()
Run Code Online (Sandbox Code Playgroud)

ekh*_*oro 14

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


Ava*_*ris 7

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

type(layout.itemAt(i)) == QtGui.QHBoxLayout
Run Code Online (Sandbox Code Playgroud)

将永远不会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)    
Run Code Online (Sandbox Code Playgroud)