18

我有一个小部件,它会在切换选项时发生变化。这会使所有布局和小部件无效。我保留了所有布局的列表,因此我可以使用类似于此答案的内容删除它们:

class MyWidget(QFrame):
   # ...
   def reLayout(self):
      def deleteLayoutChilds(l):
         while l.count():
            item=l.takeAt(0)
            widget=item.widget()
            if widget: widget.deleteLater()
            else: deleteLayoutChilds(item.layout())
      for l in self.allLayouts: deleteLayoutChilds(l)

      # now install the new layout
      ##
      ## how to delete the old layout first?
      l=self.layout(); del l # no effect
      #
      layout=QGridLayout(self)
      ## warning: QLayout: Attempting to add QLayout "" to MyWidget "", which already has a layout.

如何摆脱旧布局并设置新布局?


该文档非常简洁,显然不直接适用于 python:

QWidget.setLayout (self, QLayout)

QLayout 参数已将其所有权转移给 Qt。

将此小部件的布局管理器设置为布局。

如果这个小部件上已经安装了布局管理器,QWidget 不会让你安装另一个。您必须先删除现有的布局管理器(由 layout() 返回),然后才能使用新布局调用 setLayout()。

如果 layout 是不同小部件上的布局管理器, setLayout() 将重新设置布局并使其成为该小部件的布局管理器。

例子:

 QVBoxLayout *layout = new QVBoxLayout;
 layout->addWidget(formWidget);
 setLayout(layout);

调用此函数的另一种方法是将此小部件传递给布局的构造函数。

QWidget 将拥有布局的所有权。

另请参阅 layout() 和布局管理。

4

1 回答 1

37

您可以简单地将布局重新设置为临时小部件:

def reLayout(self):
    QWidget().setLayout(self.layout())
    layout = QGridLayout(self)
    ...

这将使所有子小部件重新成为该临时对象的父级,并且该对象连同其新子级立即被删除,因为我们不保留对它的引用。

但是,为单个小部件拥有多个布局并能够在它们之间切换的典型方法是使用QStackedWidgetor QStackedLayout


如果您仍然需要该次要问题的答案:

如何先删除旧布局?

似乎您不能直接删除QObject具有父级的 a,因为父级保留对该对象的引用。但是您可以将对象添加到一个临时对象QObjectCleanupHandler,就像上面的解决方案一样,它将立即与它包含的对象一起被删除:

QObjectCleanupHandler().add(self.layout())
于 2012-05-03T20:56:41.420 回答