2012-02-21 2 views
3

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

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

Так что мне нужно что-то, что я могу назвать рекурсивно очистить и удалить все вещи из моего родителя QVBoxLayout. Я пробовал вещи, упомянутые здесь (Clear all widgets in a layout in 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() 

ответ

11

Самый безопасный способ очистить раскладку, чтобы извлечь элементы с его методом 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()) 
+0

Это более элегантное решение. спасибо – tisaconundrum

7

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

почти там, но не совсем :) Спасибо в любом случае :) Когда я запускаю функцию, которую вы предоставили, все мои QHboxLayouts получают в виде прокладок. Так как это неверно "возвращает QLayoutItem, QWidgetItem или QSpacerItem в зависимости от элемента в этой позиции." => My itemAt возвращает QHboxLayout, который не является QLayoutItem – kosta5

+0

Я как-то исправил его следующим образом: def clearLayout (self, layout): для i в диапазоне (layout.count()): if (type (layout.itemAt (i)) == QtGui.QHBoxLayout): печати "раскладка" ул (layout.itemAt (я)) self.clearLayout (layout.itemAt (я)) еще +: печати "виджет" ул (layout.itemAt + (i)) if (type (layout.itemAt (i)) == QtGui.QWidgetItem): layout.itemAt (i) .widget(). close() – kosta5

+0

@ user965847: Это странно. Я получаю 'QLayoutItem'' за мои испытания. В любом случае, я редактировал код. Попробуй это. – Avaris

Смежные вопросы