WZX's blog 海滩上捡贝壳的孩子

QT绘图体系

2019-09-08
wzx
QT

简单概述 qgraphics 绘图系统

QPainter绘图系统

组件

  • QPainter:用于执行绘图操作,QPainter::setPen(const QPen&)设置画笔,QPainter::setBrush(const QBrush&)设置填充,QPainter::setFont(const QFont)设置字体
  • QPaintDevice:二维空间的抽象层,QPainter绘图的画布
  • QPaintEngine:提供了统一设备绘图接口,由QPainterQPaintDevice内部调用

事件

  • QWidget::paintEvent(QPaintEvent*)QWidget的绘图事件,QWidget::update()QWidget::repaint(),触发此事件

坐标系统

  • 物理坐标:QPaintDevice基本的坐标系,以左上角为原点,xy轴向右与下递增,单位为像素

  • 逻辑坐标:由物理坐标变换而来,一般中心点为原点,xy轴向右与下递增,单位没有实际意义

  • 视口坐标系:QPaintDevice中以物理坐标为基础的矩形绘图区域

  • 窗口坐标系:QPaintDevice中以逻辑坐标为基础的矩形区域,与视口坐标系的矩形为同一个

左边为视口坐标系,右边窗口坐标系,窗口坐标系使得无论 widget 的缩放,其逻辑坐标保持一致,便于绘图

QGraphics绘图体系

更高级的图形视图框架,特别对于大规模的图形项渲染较快

组件

  • QGraphicsItem:基本的图形项,自定义图形项要实现QGraphicsItem::paint(QPainter *, const QStyleOptionGraphicsItem*, QWidget*)绘图,和QGraphicsItem::boundingRect()绘图区域,qt本身已经实现了一些图形项

  • QGraphicsSceneQGraphicsItem的容器,可以附加到多个视图中
  • QGraphicsView:用于显示QGraphicsScene,提供滚动条
  • QGraphicsItem:基本的图形项

坐标系统

  • 图形项坐标:如图所示,中心为原点,单位为像素,不会随着 widget 放缩
    • 图形项在父坐标系的位置是其中心点在父坐标系的位置
    • 未设置父图形项的子图形项为顶层图形项,父坐标系为场景坐标系
    • 类内部操作时,一般只需考虑局部坐标QGraphicsItem::pos()QGraphicsItem::setPos()例外,返回父坐标中的位置
  • 场景坐标:如图所示,用于确定顶层图形项的位置,单位为像素,不会随着 widget 放缩
  • 视图坐标:如图所示,widget 的物理坐标,与场景和图形项坐标无关,需要通过坐标映射之后再操作

在需要用到不同 item 的坐标时,一定要用 mapxx函数来 统一坐标系

布局

函数原型省去了部分元素,具体参见文档

  • QGraphicsView::sceneRect():视图中的场景的可视化范围。当视图小于场景时,只对QGraphicsView::sceneRect内的图像生成滚动条,之外的图像将不能被显示
    • 计算对齐方式时,会以QGraphicsView::sceneRect为标准
    • 默认与QGraphicsScene::sceneRect两者不同)具有相同的值,并且随之变化(未设置的话)
  • QGraphicsScene::sceneRect():场景的边界矩形,用于管理图形项
    • 如果设置了QGraphicsView::sceneRect,那么QGraphicsScene::sceneRect与视图的显示无关,超出边界的item也可能被显示出来
  • QGraphicsItem::boundingRect():图形项的边界矩形。QGraphicsView通过它来重绘图形项,所以所有绘图内容必须在其内。不受图形项变换的影响

  • QGraphicsItem::shape():返回图形项的形状,由 QGraphicsItem::contains()QGraphicsItem::collidesWithPath()的默认调用实现碰撞检测,命中等

  • QGraphicsItem::zValue():图形项的堆叠顺序,0为顶层

QGraphicsItem父子关系

  • 父item属性改变,子item 也会跟着改变,如enablevisible

  • 父item传播位置改变和transform子item,即子跟着父移动,变换

  • 绘图顺序:先绘制父item,再绘制子item

  • 子itemstack order 默认在父item之前,为子item 设置 ItemStacksBehindParent,可以改变这个顺序

QGraphicsItem场景事件

QGraphicsScene将事件打包传递给子item,注意父item不会过滤掉子item的事件,除非设置了QGraphicsItem::setFiltersChildEvents(bool),事件的触发与 itemzValuestack顺序有关

  • QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value):描述了item的改变,需要设置QGraphicsItem::ItemSendsGeometryChanges才会触发

  • hoverEnterEvent hoverLeaveEvent hoverMoveEvent:鼠标徘徊事件,需要setAcceptHoverEvents(true)才会触发

REFERENCE

[1]王维波, 栗宝鹃, 侯春望. Qt 5.9 C++开发指南[M]. 人民邮电出版社, 2018.
[2]QGraphicsItem Class | Qt Widgets 5.13.1[EB/OL].


上一篇 复制构造函数

Comments

Content