【问题标题】:Changing QGraphicsItem stack order with stackBefore使用 stackBefore 更改 QGraphicsItem 堆栈顺序
【发布时间】:2020-01-13 01:25:24
【问题描述】:

我有一个 QGraphicsItem “p”,其中有 4 个孩子 a、b、c 和 d,按该顺序插入。

#include <QtWidgets/QApplication>
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/QGraphicsItem>
#include <QtWidgets/QGraphicsView>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QGraphicsScene scene(0, 0, 200, 200);
    QGraphicsView view(&scene);

    QGraphicsItem* p = new QGraphicsRectItem(nullptr);
    scene.addItem(p);
    QGraphicsRectItem* a = new QGraphicsRectItem( 0,  0, 40, 40, p);
    QGraphicsRectItem* b = new QGraphicsRectItem(10, 10, 40, 40, p);
    QGraphicsRectItem* c = new QGraphicsRectItem(20, 20, 40, 40, p);
    QGraphicsRectItem* d = new QGraphicsRectItem(30, 30, 40, 40, p);

    // cosmetic
    p->moveBy(40, 40);
    a->setBrush(Qt::blue);
    b->setBrush(Qt::red);
    c->setBrush(Qt::yellow);
    d->setBrush(Qt::green);

    view.show();

    return app.exec();
}

我想将项目 a 放在 c 和 d 之间,如下所示:

所以基本上我使用 stackBefore 并做:

a->stackBefore(d);

但它不起作用。因此,我查看了 QGraphicsItem 的代码,似乎该项目之前已经堆叠(无论是否立即堆叠)它不会移动:

// Only move items with the same Z value, and that need moving.
int siblingIndex = sibling->d_ptr->siblingIndex;
int myIndex = d_ptr->siblingIndex;
if (myIndex >= siblingIndex) {

我可以:

b->stackBefore(a);
c->stackBefore(a);

移动 a 下的所有元素。 或:

a->setParentItem(nullptr);
a->setParentItem(p);
a->stackBefore(d);

删除 a,然后将其重新插入顶部,以便我可以使用 stackBefore。

这两种解决方案看起来都不是很有效。第一个无法扩展,第二个缺乏语义。

有没有优雅的方法来实现这一点?

【问题讨论】:

  • 感谢您的提问,这解释了为什么我的 stackBefore() 呼叫不起作用,我从未正确调查过(改为使用 Z 顺序)。 :-) 看起来我们真的需要一个sortBefore() 函数来处理这个问题。令人失望的是,API 中没有任何内容,因为很多信息已经在私有部分中,并且更容易在内部处理。

标签: c++ qt qt5 qgraphicsscene qgraphicsitem


【解决方案1】:

我会为每个图形项分配一个明确的 Z 值:

int z = 0;
a->setBrush(Qt::blue);
a->setZValue(++z);
b->setBrush(Qt::red);
b->setZValue(++z);
c->setBrush(Qt::yellow);
c->setZValue(++z);
d->setBrush(Qt::green);
d->setZValue(++z);

然后,在使用stackBefore()之前,改变移动项的Z值:

a->setZValue(d->zValue());
a->stackBefore(d);

【讨论】:

  • 顺便说一句,我宁愿完全不使用 stackBefore(),而是使用每个图形项的显式 X、Y 和 Z 坐标来设计我的图形场景。 Z 是 qreal,因此您在层间提升或下沉物品时有很多可能性。
  • 我在考虑 zValue,但我发现在我的应用程序中维护它太难了(许多删除/插入)。在您的示例中,stackBefore 是无用的,因为 a 就在 d 之前。我想我现在只使用链堆栈之前
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 2022-11-17
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多