将 QWidget 上的布局替换为另一个布局



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

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(( 使用新布局。

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

例:

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

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

QWidget将拥有布局的所有权。

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

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

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

这会将所有子小部件重新设置为该临时对象,并且该对象与其新子对象一起立即删除,因为我们不保留对它的引用。

但是,为单个小部件提供多个布局并能够在它们之间切换的典型方法是使用 QStackedWidgetQStackedLayout .


如果你仍然需要这个次要问题的答案:

如何先删除旧布局?

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

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

最新更新