QT图形视图框架——坐标系统

图形项坐标

  •     以图形项的左上角为原点。
  •     创建自定义图形项时,只需要考虑图形项的坐标系统
  •     没有父图形项的是顶层图形项,在场景坐标系中,可以用setPos()函数指定图形项的位置,没有指定时出现在原点处。子图形项的坐标不会受到父图形项的变换的影响,相对于场景而言,子会随着父的变换而变换。
  •     所有图形项会使用确定的顺序来进行绘制,该顺序决定单击场景时获取鼠标的顺序。默认是父图形项先被绘制,再是子图形项,用Z值设定层叠顺序,setZValue()改变一个图形项的Z值。Z值大的在上面。子图形项默认显示在父图形项的上面。

场景坐标(QPainter的逻辑坐标)

  •     图形项的基础坐标系统,描述每一个顶层图形项的位置,原点在场景的中心
  •     每一个图形项都有本地坐标,边界矩形,场景坐标(QGraphicsItem::scenePos()),场景中的边界矩形(QGraphicsItem::sceneBoundingRect())

视图坐标(设备坐标)

    部件的坐标,原点在视图的左上角,所有鼠标事件和拖放事件都是通过视图坐标被接收

坐标映射

  •     场景映射到图形项,图形项之间的映射,视图映射到场景
  •     可以调用QGraphicsView::mapToScene()和QGraphicsScene::itemAt()以获取光标下的图形,第一个函数将视口坐标映射到场景,第二个获取场景中顶层图形项
  •     获取视口中的位置,先用QGraphicsView::mapToScene()将视口坐标映射到场景,再用QGraphicsView::mapFromScene()将场景坐标转变为视口坐标。
  •     QPoint viewPos = event->pos(); //鼠标事件返回的坐标是视口坐标
  •     QPoint scenePos = mapToScene(viewPos); //将视口坐标映射成场景坐标
  •     scene()->itemAt(scenePos); //itemAt()的参数是场景坐标,此处的场景坐标即鼠标指向的位置
  •     item->setPos(); //在没有父图形项时,作为顶层图形项,设置的参数是相对于场景原点的偏移量;有父图形项时,设置的参数是相对于父图形项的原点的偏移量
  •     item->setParentItem(rectItem); //设置父图形项,父图形项的旋转平移时,子图形项会做相应的变化

    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中心

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值