QGraphicsItem碰撞抖动/颤抖

问题描述 投票:0回答:1

我正在基于 QGraphics 框架在 Qt 中创建类似时间线的小部件。我的问题是处理时间轴轨道中的项目(继承自 QGraphicsRectItem)的碰撞。

我使用 itemChange() 函数来跟踪碰撞。为了将项目保留在父边界矩形中,我使用以下代码,它的工作原理就像一个魅力

if (change == ItemPositionChange && scene())
   if (thisRect.intersects(parentRect)) {
        const QPointF offset(mapFromParent(thisRect.topLeft()));
        QPointF newPos(value.toPointF());

        if (snapToGrid) {
            newPos.setX(floor(qMin(parentRect.right() - offset.x() - thisRect.width(),
                                   qMax(newPos.x(), parentRect.left() / 2 - offset.x())) / (snapValue * pxPerSec(duration))) * snapValue * pxPerSec(duration));
        }
        else {             
            newPos.setX(qMin(parentRect.right() - offset.x() - thisRect.width(),
                             qMax(newPos.x(), parentRect.left() - offset.x())));
        }

        newPos.setY(parentItem()->boundingRect().height() * 0.1);
        return newPos;
    }
}

如果项目到达时间轴轨道的左边界或右边界,即使我将鼠标移到视图/场景之外,也会立即停止这些项目。它就像一堵看不见的墙。 现在,如果轨道中的一个项目与另一个项目发生碰撞,我想要相同的行为。

const QRectF parentRect(parentItem()->sceneBoundingRect());
const QRectF thisRect(sceneBoundingRect());

    foreach (QGraphicsItem *qgitem, collidingItems()) {
        TimelineItem *item = qgraphicsitem_cast<TimelineItem *>(qgitem);
        QPointF newPos(value.toPointF());

        if (item) {
            const QRectF collideRect = item->sceneBoundingRect();
            const QPointF offset(mapFromParent(thisRect.topLeft()));

            if (thisRect.intersects(collideRect) && thisRect.x() < collideRect.x()) {
                newPos.setX(collideRect.left() - offset.x() - thisRect.width());
            }

            if (thisRect.intersects(collideRect) && thisRect.x() > collideRect.x()) {
                newPos.setX(collideRect.right() + offset.x());
            }

        }

        newPos.setY(parentItem()->boundingRect().height() * 0.1);
        return newPos;
    }

问题是,如果我通过鼠标将一个项目移动到另一个项目上,您会看到它们相交/重叠,然后我移动的项目会弹回到最小不相交距离。如果移动的物品撞到另一个物品,我如何设法立即停止移动的物品(没有前后移动与物品相交的颤抖)。就像项目保存在父级boundingRect(第一个代码块)中的方式一样,像隐形墙一样的行为?

c++ qt collision qgraphicsitem
1个回答
0
投票

我认为这里的问题在于“thisRect”。如果您从 ItemPositionChange 调用此方法,则 sceneBoundingRect 将返回项目在其前一位置的边界矩形,而不是新位置。发生的情况是,即使发生碰撞,当前位置也会成功,但下一个位置会失败,因为您总是检查之前的结果,然后它会弹回以避免碰撞。

获取本地项目的场景矩形后,您需要将其转换为该项目的新的未来位置:

QPointF new_pos (value.toPointF ());
QRectF thisRect (sceneBoundingRect());
thisRect.translate (new_pos - pos());

我已将“new_pos”的创建移到循环之外,以便它可用于矩形平移。速度也更快。

© www.soinside.com 2019 - 2024. All rights reserved.