1

我的 Qt 4.8.1 C++ 类绘制十字准线子类 QGraphicsItem 并实现其paint()boundingRect()方法。paint() 方法由两个 drawLine() 和一个 drawText() 调用组成。原点居中。boundingRect() 还尊重这些坐标 (-,-,+,+) 以及每个方向的半笔宽度。

在创建、移动(或定位)然后将对象添加到(可见)场景时,视图会移动几个像素,以便场景内容略微移动到右下角。如果 boundingRect() 返回一个空的 QRectF(),则不会发生这种转变。

  • 附加元素不会导致场景进一步移动。
  • 场景的先前 update() 不会改变行为
  • 更大的 boundingRect 似乎增加了运动
  • 改变视图的变换不会改变行为

itemChange() 被多次调用,但似乎没有提供线索(在我看来):

Crosshair::Crosshair being created, id= "1"  at  QPointF(63.6, 88.487) scenePos= QPointF(33.6, 58.487) 
Crosshair::Crosshair position QPointF(63.6, 88.487) 
Crosshair::itemChange  ItemFlagsChange QVariant(uint, 1) 
Crosshair::itemChange  ItemFlagsHaveChanged QVariant(uint, 1) 
Crosshair::itemChange  ItemFlagsChange QVariant(uint, 33) 
Crosshair::itemChange  ItemFlagsHaveChanged QVariant(uint, 33) 
Crosshair::itemChange  ItemFlagsChange QVariant(uint, 2081) 
Crosshair::itemChange  ItemFlagsHaveChanged QVariant(uint, 2081) 
[...]
Crosshair::itemChange  ItemPositionChange QVariant(QPointF, QPointF(63.6, 88.487) ) 
Crosshair::itemChange  ItemPositionHasChanged QVariant(QPointF, QPointF(63.6, 88.487) ) 
Crosshair::itemChange  ItemSceneChange QVariant(QGraphicsScene*, ) 
Crosshair::itemChange  ItemSceneHasChanged QVariant(QGraphicsScene*, ) 
[...]
Crosshair::boundingRect  20 3 QRectF(-11.5,-11.5 21.5x21.5) 
Crosshair::boundingRect  20 3 QRectF(-11.5,-11.5 21.5x21.5) 
Crosshair::itemChange  ItemVisibleChange QVariant(bool, true) 
Crosshair::itemChange  ItemVisibleHasChanged QVariant(bool, true) 
Crosshair::boundingRect  20 3 QRectF(-11.5,-11.5 21.5x21.5) 
Crosshair::boundingRect  20 3 QRectF(-11.5,-11.5 21.5x21.5) 
...

明天我也许可以创建一个最小的例子,但也许有人能够从这个问题的一般描述中猜出我的错误。或者,当然非常欢迎进一步调试的提示!


编辑 感谢 Riacheche 的建议。一些进一步的调试输出显示,sceneRect() 确实发生了变化,它精确地扩展了十字准线的边界矩形的大小,例如 from QRectF(0,0 1680x636)to QRectF(-11.5,-11.5 1691.5x647.5)。场景的 itemsBoundingRect 保持不变。现在我之前没有提到视图已被缩放/转换,fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio);并注意到当以 100% (例如)查看场景时确实不会发生这种转变resetTransform()。但是我仍然不明白当我在 boundingRect() 中添加一个元素时,sceneRect() 如何/为什么会发生变化。它必须与我的自定义实现有关,因为添加椭圆不会导致场景/视图的移动。

好的,我们开始吧:我也没有提到我使用setFlag(QGraphicsItem::ItemIgnoresTransformations);了这样的十字准线,无论比例如何,十字准线都保持相同的大小。这显然会导致边界矩形在添加时“停留”在场景的原点,并忽略 setPos()。

未完待续 ...

4

2 回答 2

3

场景有一个边界矩形,默认情况下它是包含所有项目的最小矩形。如果你在这个矩形之外的场景中添加一些东西,边界矩形将被扩展。

视图尊重场景的矩形。如果场景的矩形小于视图的视口大小,则视图的滚动条被隐藏并且场景内容出现在视口的中心。因此,如果您添加一个项目,场景的边界矩形会发生变化,并且所有内容都会发生变化。如果视口小于边界矩形,则出现滚动条。

如果你想避免这种行为,你可以使用QGraphicsView::setSceneRectorQGraphicsScene::setSceneRect来修复 rect 位置。请注意,设置矩形之外的所有内容都将在视图中不可用且不可见。

还可以考虑切换到QGraphicsPathItem(and QGraphicsScene::addPath)。它可以用来绘制十字准线。

于 2013-07-09T16:55:11.453 回答
0

我正在尝试是否可以解决该问题

QRectF save = scene->sceneRect();
scene->addItem( myGraphicsItem );
scene->setSceneRect( save );

正如 Riacheche 在不同的说明中所建议的那样,它确实有效。

但是,不幸的是,我仍然不完全了解造成这种情况的原因。

以下是文档对该标志的说明:

QGraphicsItem::ItemIgnoresTransformations

0x20

该项目忽略继承的转换(即,它的位置仍然锚定到其父级,但忽略父级或视图旋转、缩放或剪切转换)。这个标志对于保持文本标签项水平和未缩放很有用,因此如果视图被转换,它们仍然是可读的。设置后,项目的视图几何和场景几何将分别维护。您必须调用 deviceTransform() 来映射坐标并检测视图中的碰撞。默认情况下,此标志被禁用。这个标志是在 Qt 4.3 中引入的。注意:设置此标志后,您仍然可以缩放项目本身,并且缩放转换将影响项目的子项。

以下是一些可能相关的信息:

于 2013-07-12T09:13:53.917 回答