图形项坐标
场景坐标(QPainter的逻辑坐标)
视图坐标(设备坐标)
部件的坐标,原点在视图的左上角,所有鼠标事件和拖放事件都是通过视图坐标被接收
坐标映射
1、 Qt中事件传递是由父向子传递,同样在视图场景中事件传递是View->Scene->Item这样的顺序,所以上层的事件函数重写必须调用父类事件函数,实现事件的向下传递,不至于阻塞后面元素的事件处理。
2、 在View中调用setBackgroundBrush方法会阻止Scene中drawBackground方法的调用,这个帮助中有说明,属于帮助看的不仔细。另外View/Scene中的drawBackground和drawForeground方法类似事件函数,调用顺序是View->Scene,所以在自定义View中drawBackground和drawForeground方法时需要调用父类方法。
3、 QGraphicsScene::sceneRect和QGraphicsView::sceneRect是有区别的,QGraphicsScene::sceneRect是场景的实际范围大小,是一个抽象逻辑概念,例如用场景作为画布,为画布的实际大小。QGraphicsView::sceneRect则是在View中需要给Scene预留的区域大小,这个类似窗口概念,QGraphicsView::sceneRect的大小直接影响则View窗口中滚动条的出现。在开发中QGraphicsScene::sceneRect最好小于等于QGraphicsView::sceneRect大小,以保证在缩放View时通过滚动条可以查看到完整的Scene区域。
4、 QGraphicsItemGroup的位置问题,创建的group在场景中的初始pos()始终为(0,0),这一点与普通item不同。不知道Qt对QGraphicsItemGroup这样设计的原因是什么,把它理解成普通item确实带来不少问题,感觉是个“坑”。一般item的pos()就是item的sceneBoundingRect的左上角,所以为了统一我们也可以对group取sceneBoundingRect().topLeft()作为它的pos。对group setPos时先计算新pos与topLeft点的offset,然后通过group.setPos(group.pos()+offset)来实现group新位置移动。
5、 给Item设置新的位置,在对item进行了一些列复杂的transform变换或其他操作后,有时候会出现setPos时位置与预想的不一致,多半是item相对Scene的坐标系映射关系发生了我们未察觉的变化导致的。这个时候你再对item setPos到Scene中具体的某个点时会出现偏差,我遇见类似问题的一个思路是,不要使用setPos设置绝对的位置点,而是先求取原pos与要设置pos的offset,然后同4中那样通过item.setPos(item.pos()+offset)来实现item新位置设置,一般可以达到预期的位置。
坐标说明
QGraphicsRectItem setPos 设置在Scene中的坐标
QGraphicsRectItem item(20,20,60,60) 设置的是在item上的坐标
CustomItem *pItem = new CustomItem();
pItem->setRect(20, 20, 60, 60); //设置的使在item上的坐标
Scence->setSceneRect(0,0,800,800);//设置场景范围 //一定要定义setSceneRect,如果不定义可能会出现setPos无效
void GraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsRectItem * item1 = addRect(event->scenePos().toPoint().x(),event->scenePos().toPoint().y(),10,10,QPen("yellow")); //这个方框在 item坐标的 event.x event.y
item1->setPos(event->scenePos().x(),event->scenePos().y());
QGraphicsRectItem * item2 = addRect(0,0,10,10,QPen("red")); //这个方框在 item坐标的 0,0
item2->setPos(event->scenePos().x(),event->scenePos().y());
}
QGraphicsItem::scenePos() //获取scene 坐标
QGraphicsItem::sceneBoundingRect() //获取 scene 坐标的边界矩形
View->centerOn(point); //point 为scene坐标, 让point坐标位于view中心