Удалить виджеты и макет, а также - PullRequest
3 голосов
/ 21 февраля 2012

Я пытался найти что-то, что могло бы взять макет 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 ]

13 голосов
/ 21 февраля 2012

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

Проблема с вашим кодом: 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)    
...