【问题标题】:Getting Parent Layout in Qt在 Qt 中获取父布局
【发布时间】:2011-01-25 10:57:37
【问题描述】:

快速提问。有没有办法(轻松)在 Qt 中检索小部件的父布局?

PS:出于逻辑原因,QObject::parent() 不起作用。

编辑: 我很肯定这个小部件有一个父布局,因为我在代码的前面将它添加到了一个布局中。现在,我在窗口中有许多其他布局,虽然我可以跟踪它们,但我只想知道是否有一种简单而干净的方法来获取父布局。

编辑2: 抱歉,“简单而干净”可能不是最好的放置方式。我的意思是使用 Qt API。

编辑3: 我正在像这样将小部件添加到布局中:

QHBoxLayout* 布局 = 新 QHBoxLayout;

布局->addWidget(按钮);

【问题讨论】:

  • 返回父窗口。
  • @Ronny,因为 QLayouts 只是管理者。布局中的托管对象仍然是其各自父级的子级(如窗口)。这样小部件就不会依赖于它们被管理的布局(如果有的话)。
  • 哦,我明白了。现在我明白了。
  • 该死的,伙计们。今天所有奇怪的反对票是怎么回事?似乎SO变得越拥挤,就越有人想玩严肃的版主业务。 ://
  • 您能否展示如何创建小部件和设置布局?或者至少解释一下,你说“我在代码的前面将它添加到布局中”是什么意思。

标签: c++ qt layout parents


【解决方案1】:

(更新答案)

我想这并不容易。因为从技术上讲,一个 Widget 可以包含在多个布局中(例如,在垂直布局内对齐的水平布局)。

请记住,如果 QWidget 在布局中对齐,它的父级不会改变。

那么,您可能必须自己跟踪。

【讨论】:

  • 返回包含在你的小部件中的布局(如果有的话),而不是包含你的小部件的布局。
  • 这会返回安装在小部件上的布局,而不是小部件的父布局(即该小部件所在的布局)。
  • 但是 parent().layout() 应该做他们想做的事。
  • @McBeth,它没有。小部件仍然是窗口的子窗口,而不是布局。
  • @BastiBense 当然,小部件是其父小部件的子小部件。但是那个父小部件有一个布局(由 OP 断言),它可能有更多的布局,但原始小部件会在某个地方。
【解决方案2】:

已解决! 用法:QLayout* parentLayout = findParentLayout(addWidget)

QLayout* findParentLayout(QWidget* w, QLayout* topLevelLayout)
{
  for (QObject* qo: topLevelLayout->children())
  {
     QLayout* layout = qobject_cast<QLayout*>(qo);
     if (layout != nullptr)
     {
        if (layout->indexOf(w) > -1)
          return layout;
        else if (!layout->children().isEmpty())
        {
          layout = findParentLayout(w, layout);
          if (layout != nullptr)
            return layout;
        }
     }
  }
  return nullptr;
}

QLayout* findParentLayout(QWidget* w)
{
    if (w->parentWidget() != nullptr)
        if (w->parentWidget()->layout() != nullptr)
            return findParentLayout(w, w->parentWidget()->layout());
    return nullptr;
}

【讨论】:

    【解决方案3】:

    简单使用:

    QHBoxLayout* parentLayout = button->parentWidget()->layout();
    

    我假设 button 是包含 layout 的小部件的子组件,其中包含 buttonbutton-&gt;parentWidget() 返回一个指向按钮 parentwidget 的指针,-&gt;layout() 返回指向父级 layout 的指针。 p>

    【讨论】:

    • 请注意,这在一般情况下不起作用。这个警告隐含在这个答案中(“我假设按钮是包含包含按钮的布局的小部件的子级。”),但@BastiBen 在他的回答中明确表示: “从技术上讲,一个小部件可以包含在多个布局中(例如,在垂直布局内对齐的水平布局)。” 因此,如果您打算使用此解决方案,请记住这一点。
    【解决方案4】:

    使用 widget.parent().layout() 和搜索蛮力(包括递归)是我唯一的建议。也许你可以搜索“名字”。

    【讨论】:

    • 我已经尝试过 QObject::parent() 但它不起作用。它返回父窗口。
    • 这意味着没有父布局。
    • 如果它是一个小部件,你可能想要使用 widget.layout() 如果这是你想要的
    • 对我来说看起来你必须从这个父小部件布局开始用蛮力搜索。我会进一步挖掘。
    【解决方案5】:

    经过一番探索,我找到了解决问题的“部分”解决方案。

    如果您正在创建布局并使用它管理小部件,则可以稍后在代码中使用 Qt 的动态属性检索此布局。现在,要使用 QWidget::setProperty(),您要存储的对象需要是已注册的元类型。指向 QHBoxLayout 的指针不是已注册的元类型,但有两种解决方法。最简单的解决方法是通过在代码中的任何位置添加此对象来注册对象:

    Q_DECLARE_METATYPE(QHBoxLayout*)
    

    第二种解决方法是包装对象:

    struct Layout {
        QHBoxLayout* layout;
    };
    Q_DECLARE_METATYPE(Layout)
    

    一旦对象是一个注册的元类型,你可以这样保存它:

    QHBoxLayout* layout = new QHBoxLayout;
    QWidget* widget = new QWidget;
    widget->setProperty("managingLayout", QVariant::fromValue(layout));
    layout->addWidget(widget);
    

    如果您使用了第二种解决方法,也可以这样:

    QHBoxLayout* layout = new QHBoxLayout;
    QWidget* widget = new QWidget;
    Layout l;
    l.layout = layout;
    widget->setProperty("managingLayout", QVariant::fromValue(l));
    layout->addWidget(widget);
    

    以后需要取回布局时,可以这样取回:

    QHBoxLayout* layout = widget->property("managingLayout").value<QHBoxLayout*>();
    

    或者像这样:

    Layout l = widget->property("managingLayout").value<Layout>();
    QHBoxLayout* layout = l.layout;
    

    此方法仅在您创建布局时适用。如果您没有创建布局并设置它,那么以后就没有简单的方法来检索它。此外,您还必须跟踪布局并在必要时更新managementLayout 属性。

    【讨论】:

      【解决方案6】:

      你试过吗?不要忘记检查 NULL。

      QLayout *parent_layout = qobject_cast< QLayout* >( parent() );
      

      如果 parent_layout 等于 NULL,则父窗口小部件不是布局。

      【讨论】:

      • 我很肯定这个小部件有一个父布局。
      • See doc: "布局将自动重新设置小部件的父级(使用 QWidget::setParent()),以便它们是安装了布局的小部件的子级。"
      【解决方案7】:

      你试过QWidget::layout()吗?

      【讨论】:

      • 其他人已经提出了这个建议,但把它删掉了。这个不起作用 - 原因是它返回安装在小部件上的布局,而不是包含您的小部件的布局。
      • 父布局是什么意思呢?当您将小部件放入 Designer 中的布局时,实际上是在小部件上安装了该布局,该布局不会成为该小部件的 QObject::parent()。如果您从 .ui 文件中查看由uic 生成的 .h 文件,您可以很容易地看到这一点。
      • 我的意思是,在将我的小部件放置在布局 A 中之后,是否可以使用 Qt 的 API 在代码中稍后检索布局 A?
      • 您如何将您的小部件“放置”到布局中?如果你调用A-&gt;addWidget(widget),那么widget-&gt;layout() 应该返回A。如果您创建像widget = new QWidget(A) 这样的小部件,那么qobject_cast&lt;QLayout*&gt;(widget-&gt;parent()) 应该返回A。
      • 我正在做 A->addWidget(widget)。我已经尝试过了,它返回一个空指针(0)。此外,widget = new QWidget(A) 是不可能的,因为布局不是 QWidget 并且 QWidget 的构造函数需要一个指向 QWidget 的指针。
      猜你喜欢
      • 2011-05-03
      • 1970-01-01
      • 2013-07-26
      • 2017-08-08
      • 1970-01-01
      • 2016-04-20
      • 2013-02-18
      • 1970-01-01
      • 2012-02-17
      相关资源
      最近更新 更多