【问题标题】:Use the same widget in two different layouts in Qt在 Qt 的两种不同布局中使用相同的小部件
【发布时间】:2017-04-11 08:44:39
【问题描述】:

我想在 Qt 的两个不同布局中使用相同的小部件。这是我的代码:

QWidget *myWidget = new QWidget;

QFormLayout *layout1 = new QFormLayout;
layout1->addWidget(myWidget);

QFormLayout *layout2 = new QFormLayout;
layout2->addWidget(myWidget);

小部件在layout2 中应有的样子,但在layout1 中不可见。

一种解决方法是创建两个不同的myWidget 小部件,但我想知道是否有更好的方法。

为什么会发生这种情况,正确的做法是什么?

【问题讨论】:

  • 您是否希望小部件同时显示在两个不同的位置?
  • @VaughnCato 是的(虽然两种布局不会同时显示)
  • 如果您觉得需要将同一个小部件放在多个布局上,也许您应该考虑在模型/视图设计中拆分它,使用两个指向同一模型的小部件。

标签: c++ qt layout widget


【解决方案1】:

addWidget 将所有权从layout1 转移到layout2
对象树是 Qt 用来组织对象的方式。例如,具有父项的项目显示在其父项的坐标系中,并被其父项的边界以图形方式裁剪
您可以尝试解决这个限制,但这不是您应该如何使用 Qt,我不会建议它。
如果您需要两个小部件,请创建两个小部件。这就是 Qt 的设计方式和使用方式。

有关 Qt 对象模型的更多详细信息,请参阅here

【讨论】:

  • IIRC 布局不保留所有权,他们只是将其委托给他们的父母。请注意,布局的父级是QWidgetQLayout 本身不是从小部件派生的,因此即使在嵌套布局的情况下,父级也是最底部的小部件。此外,QWidget 的父级也是一个小部件,而不是 QObject,因此布局不可能拥有小部件的所有权,即使对我来说这更有意义。
  • @ddriver QFormLayout 继承 QLayout 而后者继承 QObject (至少文档是这样说的)。 addWidget 调用 addItem(请参阅 doc.qt.io/qt-5/qlayout.html#addItem),并且文档再次指出 - 项目的所有权转移到布局,布局负责删除它。所以你的推理在某处有缺陷。
  • @ddriver 我再次阅读了您的评论。我现在明白你的意思了。好吧,答案仍然适用,我不明白这样的评论需要如何改变它。您是否建议添加更多细节或其他内容?
  • In 继承 QObject 但不继承 QWidget,而每个 QWidget 都是 QObject,并非每个 QObject 都是 QWidget。如果你做一个简单的测试,你会意识到一旦你将一个小部件添加到布局中,小部件的父级将不是布局,而是底层小部件。也许它只是一个糟糕的文档的例子,有很多这样的例子。答案本身没有问题,我只是澄清一下。
  • @ddriver 是的,我明白了。谢谢你。我试图理解其中的原因,仅此而已。我想它也可以被解释为就像的一个例子,不仅仅是文档中的错误。它更容易理解,实际上它就像一样工作。无论如何,谢谢你的澄清。
【解决方案2】:

您不能在多个地方拥有相同的对象。它只有一个实例,它只存在于一个位置。您只能有多个参考。诚然,布局不采用小部件实例,而是对其的引用(指针),但 Qt 的设计是,将小部件添加到布局会将所有权转移到布局的底层小部件。这是有道理的,两种布局可能需要不同的小部件几何形状,而单个小部件如何同时具有两个几何形状?即使理论上可能,如果不将几何图形从小部件中抽象出来也是不可能的,而在 Qt 的情况下,几何图形是小部件的一部分,所以这是不可能的。而这只是使此类重用/共享具有挑战性且不真正可行的众多方面之一。

根据你想要达到的目标,你可以:

  • 重用 GUI 元素 - 在这种情况下推出 YourOwnWidget : public QWidget,然后您可以根据需要多次实例化

  • 在多个 GUI 元素之间共享相同的数据,除了上一步,您真正想要做的是将 数据 放在一个单独的、不可见的对象中,然后您可以根据需要创建和绑定任意数量的 GUI 元素类型和实例。

【讨论】:

    【解决方案3】:

    您可以使用QGraphicsView。定义QGraphicsView的一个实例并将其添加到layout1

    QGraphicsView *gv1 = new QGraphicsView();
    layout1->addWidget(gv1);
    

    定义另一个并添加到layout2

    QGraphicsView *gv2 = new QGraphicsView();
    layout2->addWidget(gv2);
    
    QGraphicsScene *qc = new QGraphicsScene();
    qc->addWidget(myWidget);
    

    现在为您的 QGraphicsView 对象设置场景

    gv1->setScene(qc);
    gv2->setScene(qc);
    

    之后,您将拥有两个包含相同小部件的视图。

    【讨论】:

      猜你喜欢
      • 2011-04-15
      • 2012-09-20
      • 2011-11-10
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 2018-07-14
      相关资源
      最近更新 更多