Graphics View基于笛卡尔坐标系。item在场景中的位置与几何形状通过x,y坐标表示。当使用未经变形的视图来观察场景时,场景中的一个单位等于屏幕上的一个像素。在Graphics View中有三个有效的坐标系统:Item坐标系,场景坐标系,视图坐标系。为了简化你的实现,Graphics View提供了方便的函数,允许三个坐标系之间相互映射。
当渲染时,Graphics View的场景坐标对应于QPainter的逻辑坐标,视图坐标与设备坐标相同。
Item坐标
Items位于它们自己的坐标系中。它的坐标都以点(0,0)为中心点,这也是所有变换的中心点。在item坐标系中的几何图元,经常被称为item点,item线,item矩形。当创建一个定制的item,item坐标是所需要考虑的。QGraphicsScene与QGraphicsView可以为你执行所有转换,这使得实现定制的item变得容易。举例来说,假如你收到鼠标按或是拖进入事件,事件的位置以item坐标的形式给出。QGraphicsItem::contain()虚函数,当某个点的位置在你的item范围内时,返回true,否则返回false。这个点参数使用item坐标,相似地,item的包围矩形与形状也使用item坐标。
Item位置指的是item的中心点在它父亲的坐标系中的坐标。以这种思想来看,场景指的就是那些祖先最少的item的“父亲”。最上级的Item位置就是在场景中的位置。
子坐标与父坐标之间是相关的,假如孩子未经变换,子坐标与父坐标之间的差值等于在父坐标系下,父item与子item之间的距离。例如,假如一个未经变换的子item位置与其父item的中心重合,那么这两个item的坐标系统完全相同。如果孩子的位置是(10,0),那么孩子坐标系中的(0,10)点,对应于父坐标系中的(10,10)点。
因为item的位置与变换是相对于父item的,子item的坐标不会被父亲的变换影响,尽管父item的变换隐含地对子item做了变换。在上面的例子中,即使父item旋转,缩放,子item的(0,10)点依然对应于父item的(10,10)点。然而,相对于场景来讲,子item会遵循父item的变换。假如父item被缩放(2X,2X),子item的位置在场景中的坐标是(20,0),它的(10,0)点则与场景中的(40,0)对应 。除了QGraphicsItem::pos(),QGraphicsItem的函数以Item坐标工作,如一个item's包围矩形总是以item坐标的形式给出。
场景坐标
场景坐标系统描述了每个最顶级item的位置,也是从视图向场景投递场景事件的基础。场景中的每个item有场景位置与包围矩形(QGraphicsItem::scenePos(),QGraphicsItem::sceneBoundingRect()), 另外,它有自己本地item位置与包围矩形。场景位置描述了item在场景坐标下的位置,它的场景包围矩形则用于QGraphicsScene决定场景中哪块区域发生了变化。场景中的变化通过QGraphicsScene::changed()信号来通知,它的参数是场景矩形列表。
视图坐标
视图坐标是widget的坐标,视图坐标中每个单位对应一个像素。这种坐标的特殊之处在于它是相对于widget或是视口的,不会被所观察的场景所影响。QGraphicsView的视口的左上角总是(0,0),右下角总是(视口宽,视口高)。所有的鼠标事件与拖拽事件,最初以视图坐标表示,就应该把这些坐标映射到场景坐标以便与item交互。
坐标映射
经常,处理场景中item时,在场景与item之间,item与item之间,视图与场景之间进行坐标映射,形状映射是非常有用的。举例来讲,当你在QGraphicsView的视口中点击鼠标时,你应该通过调用QGraphicsView::mapToScence()与QGraphicsScene::itemAt()来获知光标下是场景中的哪个item。假如你想获知一个item位于视口中的什么位置,你应该先在item上调用QGraphicsItem::mapToScene(),然后调用QGraphicsView::mapFromScene()。最后,假如你想在一个视图椭圆中有哪些items,你应该把QPainterPath传递到mapToScene(),然后再把映射后的路径传递到QGraphicsScene::items()。
你可以调用QGraphicsItem::mapToScene()与QGraphicsItem::mapFromScene()在item与场景之间进行坐标与形状的映射。也可以在item与其父item之间通过QGraphicsItem::mapToParent()与QGraphicsItem::mapFromItem()进行映射。所有映射函数可以包括点,矩形,多边形,路径。视图与场景之间的映射也与此类似。对于从视图与item之间的映射,你应该首先映射到场景,然后再从场景向item进行映射。