Удалить виджеты и макет, а также

Я пытался найти что-то, что бы взять макет qt и удалить из него все. Просто чтобы представить, как выглядит окно - у меня есть:

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

Поэтому мне нужно что-то, что я могу вызвать рекурсивно, чтобы очистить и удалить все вещи от моего родителя 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()

Но это дает ошибку:

               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 ответа

Решение

Самый безопасный способ очистить макет - извлечь элементы с помощью метода 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())

Проблема с вашим кодом QLayout.itemAt() возвращает QLayoutItem, QWidgetItem или же QSpacerItem в зависимости от предмета в этой позиции. Итак, условие:

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)    
Другие вопросы по тегам