【问题标题】:Constraining child QGraphicsItem to scene?将子 QGraphicsItem 约束到场景?
【发布时间】:2016-11-02 01:48:09
【问题描述】:

有没有人有更好的方法将QGraphicsItem 的孩子限制在场景中?

我已经通过覆盖 itemChange 成功地将父 QGraphicsItem 约束到其场景,但现在我需要为子 QGraphicsItem 做同样的事情。

示例用例:

此代码在大多数情况下都有效。唯一的问题是QGraphicsItem 撞击任一侧时的速度会影响其终点位置

QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change,
                                              const QVariant &value)
{
    QPointF newPos = value.toPointF();
    if (change == ItemPositionChange)
    {
        if(scene())
        {
            newPos.setY(pos().y()); // Y-coordinate is constant.

            if(scenePos().x() < 0 ) //If child item is off the left side of the scene,
            {
                if (newPos.x() < pos().x()) // and is trying to move left,
                {
                  newPos.setX(pos().x()); // then hold its position
                }
            }
            else if( scenePos().x() > scene()->sceneRect().right()) //If child item is off the right side of the scene,
            {
                if (newPos.x() > pos().x()) //and is trying to move right,
                {
                  newPos.setX(pos().x()); // then hold its position
                }
            }
        }
    }
 return newPos;
}

对于父项,我使用了: newPos.setX(qMin(scRect.right(), qMax(newPos.x(), scRect.left()))); 效果很好,但我不知道如何或是否可以在这里使用它。

【问题讨论】:

  • 到场景还是查看?
  • 问题在于添加速度的代码,在调用setPos 之前,您应该不需要在itemChange 中执行此操作。你能显示那个代码吗?
  • 我没有那个代码。滑块的移动速度与鼠标拖动它的速度一样快。

标签: c++ qt parent-child qgraphicsscene qgraphicsitem


【解决方案1】:

首先,具体来说,场景实际上没有界限。您要做的是将项目约束到您在其他地方设置的场景矩形。

我看到的问题在于您使用 scenePos。这是一个 ItemPositionChange;该项目的 scenePos 尚未更新为新位置,因此当您检查 scenePos 是否超出场景矩形时,您实际上是在检查上次位置更改的结果,而不是当前位置更改的结果。正因为如此,您的项目最终会离开场景矩形的边缘,然后粘在那里。离边缘多远取决于您移动鼠标的速度,这决定了 ItemPositionChange 通知之间的距离。

相反,您需要将新位置与场景矩形进行比较,然后将返回的值限制在场景矩形内。您需要场景坐标中的新位置来进行比较,因此您需要类似:

QPoint new_scene_pos = mapToScene (new_pos);

if (new_scene_pos.x() < scene()->sceneRect().left())
    {
    new_scene_pos.setX (scene()->sceneRect().left());
    new_pos = mapFromScene (new_scene_pos);
    }

显然,这不是完整的代码,但这些是您需要进行的转换和检查才能将其保留在左侧。右边很相似,直接用new_scene_pos来对比就行了。

请注意,我没有假设 sceneRecT 的左边缘为 0。我确定这就是您在设置 sceneRect 的位置编码的内容,但是使用实际的左值而不是假设它为 0 可以消除任何问题,如果您稍后会更改您计划使用的场景坐标范围。

我在 sceneRect 调用中使用“left”而不是“x”只是因为它与另一侧使用“right”平行。它们完全相同,但我认为在这种情况下读起来会稍微好一些。

【讨论】:

  • mapToScene 是我需要研究的函数。在修改了mapFromScenemapToScenemapFromParentmapToParent 之后,我找到了我需要的东西:mapToScene(mapFromParent(newPos))
猜你喜欢
  • 2015-04-17
  • 2021-09-29
  • 2023-03-28
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多