Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove all items from a layout

I was trying to find something that would take a qt layout and delete everything from it. Just to imagine what the window looks like - I have:

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

So I need something that I can call recursively to CLEAR AND DELETE all the stuff from my parent QVBoxLayout. I tried things mentioned here (Clear all widgets in a layout in pyqt) but none of them work (no correct answer marked anyway). My code looks like this:

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()

But it gives an error:

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

=>EDIT This kinda works (but doesn't if there is any other Layout than 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()
like image 880
kosta5 Avatar asked Feb 21 '12 08:02

kosta5


People also ask

How do I remove a widget from layout?

layout()->removeAt(widget); delete widget; If you use takeAt(index) in a QLayout (or its children), it gives you a QLayoutItem. To access the widget inside, just use widget(). But there's no way to remove the widget without deleting it.

How do I delete a layout element?

Right-click inside the Layout window and click Delete. The element is removed from the page layout and the Layout window.


2 Answers

The safest way to clear a layout is to extract the items with its takeAt method, and then explicitly delete any widgets with 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())
like image 132
ekhumoro Avatar answered Sep 18 '22 22:09

ekhumoro


The problem with your code is QLayout.itemAt() returns a QLayoutItem, QWidgetItem or QSpacerItem depending on the item at that position. So the condition:

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

will never be True and you will be trying to do .widget() for a QLayoutItem and that returns None. Thus the error you get. Another thing is, you need to loop backwards. Because removing things from the beginning will shift items and change the order of items.

You need to write your function like this:

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)    
like image 38
Avaris Avatar answered Sep 20 '22 22:09

Avaris