用另一个布局替换QWidget上的布局

22

我有一个小部件,当选项切换时会改变。这将使所有布局和小部件无效。我保留了所有布局的列表,因此我可以使用类似于这个答案中的方法删除它们:

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。

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

如果此小部件上已经安装有布局管理器,则QWidget不会允许您安装另一个。在调用setLayout()设置新布局之前,必须先删除现有的布局管理器(由layout()返回)。

如果layout是其他小部件上的布局管理器,则setLayout()将重新指定该布局,并将其设置为此小部件的布局管理器。

示例:

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

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

QWidget 将接管布局。

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

1个回答

41

你可以将布局简单地移动到临时小部件中:

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

这将使所有子部件都被转移到临时对象中,并且由于我们不保留对该对象的引用,因此该对象和它的新子项将立即被删除。

但是,对于单个小部件具有多个布局并能在它们之间切换的典型方法是使用QStackedWidgetQStackedLayout


如果您仍需要回答次要问题:

如何先删除旧布局?

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

QObjectCleanupHandler().add(self.layout())

6
使用QObjectCleanupHandler()解决方案删除布局,这个想法不错,可以给它点赞(+1)。 - astrojuanlu
临时的QWidget解决方案就像C ++赋值运算符惯用语一样聪明。因此,您无需担心旧布局的子级销毁问题。 - heLomaN
我认为QStackedWidgetQStackedLayout是用于显示多个小部件,而不是单个小部件的多个布局。尽管如此,重新父类化的解决方案非常方便! - Ian Liu Rodrigues

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接