Qt:有选择的项目出现在QGraphicsScene顶部

Qt: having selected items appear on top in QGraphicsScene

本文关键字:QGraphicsScene 顶部 项目 有选择 Qt      更新时间:2023-10-16

所以我有一个QGraphicsScene与各种项目。其中一些可以在场景中使用相同的坐标。当我显示场景时,上面显示的是最后添加的。是否有一种方法可以使某个项目总是出现在顶部,甚至更好地使它在程序期间重新出现在顶部(而不是删除它并再次添加它)?我一直在考虑事先绘制一切,然后使用setVisible()只显示我想要的项目,但由于我想在网上添加新的东西,这似乎有点问题。

可以使用QGraphicsItem::setZValue ( qreal z )设置该项的z值。Z值决定兄弟项的堆叠顺序。具有较高Z值的项将始终绘制在具有较低Z值的另一个项的顶部。默认Z值为零。所以你可以设置一个更大的值,把它放在顶部:

item->setZValue(1);

或将其置于其他项的底部:

item->setZValue(-1);

在做了一些研究之后,我认为@Leslie的答案在某种程度上比@Nejat的答案更正确。然而,如果你有很多项目,并且你必须经常检查,那么它是非常低效的。

在我的情况下,我有一个QGraphicsTextItem,显示光标在我的场景中的坐标。

void QCVN_SceneView::mouseMoveEvent(QMouseEvent *event)
{
  QPointF cursorPoint = mapToScene(event->pos());
//  cout << "Event pos: x=" << event->pos().x() << ", y=" << event->pos().y() << endl;
//  cout << "Event pos (in scene): x=" << cursorPoint.x() << ", y=" << cursorPoint.y() << endl;
  QString coords = QString("%1, %2")
                          .arg(cursorPoint.x())
                          .arg(cursorPoint.y());
  cursorSceneCoords->setPlainText(coords);
  cursorSceneCoords->setPos(cursorPoint);
  QGraphicsView::mouseMoveEvent(event);
}

显然,如果我在场景中使用setZValue(1)有10000000个项目将无法做到这一点,除非所有项目的z-value都低于1。遍历整个项目列表也是一种糟糕的方法。

我稍微想了一下,当我想起setZValue()使用了qreal参数时,我突然想到。根据系统的不同,它可以是doublefloat,但这并不重要。我们可以简单地使用std::numeric_limits来获得尽可能高的值。当然,我们必须限制场景中的所有道具(除了我们想要在顶部的道具)的最大z-value为最大可能值减去 1(或0.1或其他)。所以如果你做

YOUR_GRAPHICS_ITEM.setZValue(std::numeric_limits<qreal>::max());

这个问题有点令人困惑。主题提到希望在选择时将项目放在最上面,而描述则讨论了更永久的排序问题(创建等)。我添加这个答案是为了澄清那些来这里的人可能的解决方案,因为这个主题:

  • 对于永久订单深度管理,setZValue是可行的。例如,一个具有组背景的节点视图,背景应该总是在所有其他项目的后面,zValue可以设置为-100。
  • 对于临时排序,例如选择,您不想与永久排序(应该保留给用户设置或特定于应用程序的顺序状态需求)混淆,您可以使用stackBefore。这将改变在相同的 zDepth 项的顺序。因此,当项目被选中时,您可以运行所有项目并调整顺序,您不必担心试图将zDepth重置回之前的状态(我想您仍然可能想要恢复,但至少这种方式将关注点与zDepth分开)。注意,FWIW,我发现stackBeforesibling顺序感觉倒了。

检查

http://www.qtcentre.org/threads/5428-help-with-ZValue ! !

// Find largest Z
qreal maxZ = 0;
foreach (QGraphicsItem *item, 
        clickedItem>collidingItems(Qt::IntersectsItemBoundingRect))
    maxZ = qMax(maxZ, item->zValue());
// Assign new Z
clickedItem->setZValue(maxZ + some);

https://github.com/sonichy/HTYPaint2/blob/master/mainwindow.cpp#L775

void MainWindow::on_action_layerTop_triggered()
{
    if(scene->selectedItems().size() > 0){
        QList<QGraphicsItem*> collidingItems = scene->collidingItems(scene->selectedItems().first());
        for(int i=0; i<collidingItems.size(); i++){
            collidingItems.at(i)->stackBefore(scene->selectedItems().first());
        }
        scene->update();
    }
}