5
datainputHbox = QHBoxLayout()
layout = QVBoxLayout(self)
layout.addLayout(datainputHbox)


pagedatainputdeletboxbutton1.clicked.connect(lambda:self.boxdelete(datainputHbox))

def boxdelete(self, box):

This is the PyQt proragm How write boxdelete funtion in order to remove datainputHbox form layout. I try a lot of. However I just can remove all the widgets but cannot remove layout.

yuwei
  • 61
  • 1
  • 1
  • 3

4 Answers4

7

As a generic answer: taken from here with slight, but important changes: you should not call widget.deleteLater(). At least in my case this caused python to crash

Global Function

def deleteItemsOfLayout(layout):
     if layout is not None:
         while layout.count():
             item = layout.takeAt(0)
             widget = item.widget()
             if widget is not None:
                 widget.setParent(None)
             else:
                 deleteItemsOfLayout(item.layout())

together with the boxdelete function from Brendan Abel's answer

def boxdelete(self, box):
    for i in range(self.vlayout.count()):
        layout_item = self.vlayout.itemAt(i)
        if layout_item.layout() == box:
            deleteItemsOfLayout(layout_item.layout())
            self.vlayout.removeItem(layout_item)
            break
TheTrowser
  • 363
  • 4
  • 14
2

You can remove QLayouts by getting their corresponding QLayoutItem and removing it. You should also be storing references to your Layouts, otherwise there is no other way to access them later on unless you know the widget they belong to.

datainputHbox = QHBoxLayout()
self.vlayout = QVBoxLayout(self)
layout.addLayout(datainputHbox)
pagedatainputdeletboxbutton1.clicked.connect(lambda: self.boxdelete(datainputHbox))

def boxdelete(self, box):
    for i in range(self.vlayout.count()):
        layout_item = self.vlayout.itemAt(i)
        if layout_item.layout() == box:
            self.vlayout.removeItem(layout_item)
            return
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • `removeItem` does not delete the object entirely, which can cause it to remain in Python due to its reference counter/garbage collector. From the [pyqt5 docs][https://doc.qt.io/qt-5/qlayout.html#removeItem], "Removes the layout item item from the layout. It is the caller's responsibility to delete the item." – adam.hendry Feb 10 '22 at 18:12
1

A single function that implements TheTrowser's answer, arguably cleaner:

def clear_item(self, item):
    if hasattr(item, "layout"):
        if callable(item.layout):
            layout = item.layout()
    else:
        layout = None

    if hasattr(item, "widget"):
        if callable(item.widget):
            widget = item.widget()
    else:
        widget = None

    if widget:
        widget.setParent(None)
    elif layout:
        for i in reversed(range(layout.count())):
            self.clear_item(layout.itemAt(i))
adam.hendry
  • 4,458
  • 5
  • 24
  • 51
1

Using the stuff above, I made a function that deletes all layouts and their widgets. Unfortunately, it also destroys other instances of said layouts and widgets, so use this with caution.

def clearLayout(self, layout: QLayout):
    """
    Args:
        layout (QLayout): The layout to clear
    """
    if layout is not None:
        while layout.count():
            item = layout.takeAt(0)
            if item is not None:
                while item.count():
                    subitem = item.takeAt(0)
                    widget = subitem.widget()
                    if widget is not None:
                        widget.setParent(None)
                layout.removeItem(item)
desl8
  • 39
  • 5