Qt图形视图框架(Graphics View Framework)

前言

  Qt的图形视图框架支持对大量的自定义2D图形项进行管理和交互,能够有效的实现图形项的可视化,并支持缩放和旋转。
  该框架包括一个事件传播架构,提供与场景中的图形项进行精确的双精度交互的能力;该事件传播框架可以处理按键事件、鼠标按下、移动、释放和双击事件,还可以跟踪鼠标移动事件。
  图形视图框架使用BSP(二元空间分割)树来实现对图形项的快速查找发现,因此,它可以实时地可视化大型场景(即使有数百万个项目)。

图形视图架构

 图形视图提供了一种基于图形项的模型视图编程方法,主要由场景(QGraphicsScene )、视图(QGraphicsView)和图形项(QGraphicsItem)三部分组成;多个视图可以查看一个场景,一个场景可包含各种图形项。
在这里插入图片描述

场景

 QGraphicsScene提供了图形视图的场景,场景具备以下能力:

  • 提供用于管理大量图形项的高速接口
  • 传播事件到每一个图形项
  • 管理图形项的状态,例如旋转和获取焦点
  • 提供无变换的渲染功能,主要用于打印

 一个场景可分为3层:图形项层(ItemLayer)、前景层(ForegroundLayer)、背景层(BackgroundLayer)。场景的绘制总是从背景层开始,然后是图形项层,最后是前景层。前景层和背景层都可以使用QBrush进行填充,比如使用渐变和贴图等。

 场景作为图形项的容器,通过调用QGraphicscene :: addItem()将图形项添加到场景中,通过调用任意一个图形项查找函数(有多个)来检索项目,例如:QGraphicscene :: items()及其重载函数用于返回指定的点、矩形、多边形或常规向量路径包含或与之相交的所有图形项。QGraphicscene :: itemAt()返回特定点上最上面的图形项,所有图形项查询函数都以降序堆叠的顺序返回图像(即,第一个返回的图形项是最上面的,最后一个图形项是最下面的)。

 QGraphicsScene的事件传播构架可以将场景事件传递给图形项,也可以管理图形项之间事件的传递。例如,如果场景在一个特定的点接收到了一个鼠标按下事件,那么场景就会把这个事件传递给该点的图形项。
 QGraphicsScene同时也管理图形项的状态,例如图形项的选择和获取焦点。 通过QGraphicsScene :: setSelectionArea()可选择任意形状内的图形项;调用QGraphicscene :: selectedItems()函数可获取所有当前选择的图现项的列表。QGraphicscene处理的另一个状态是图形项是否具有键盘输入焦点。可以通过调用QGraphicscene :: setFocusItem()或QGraphicsItem::setFocus()来设置图形项的焦点,或者通过调用QGraphicscene :: focusItem()来获取当前具备焦点的图形项。

 QGraphicscene支持通过调用QGraphicscene :: render()函数将场景的一部分渲染到打印设备中,以进行内容打印操作。

视图

  QGraphicsView提供了视图部件,它用来实现对场景中内容的可视化。可以将多个视图关联到同一个场景,以实现为一个场景中相同的数据集提供多个视口。视图部件是一个可滚动的区域,它提供了滚动条来浏览大的场景。默认的QGraphicsView是以QWidget作为视口部件,如果要使用OpenGl进行渲染,则可调用QGraphicsView :: setViewport()将QOpenGlWidget设置为视口。

 视图接收来自键盘和鼠标的输入事件,并将这些事件转换为场景事件(视情况将视图坐标转换为场景坐标),然后将事件发送到被可视化的场景。
 使用视图的变换矩阵QGraphicsView::transform(),视图可以变换场景的坐标系。使其支持高级的导航功能,如缩放和旋转。同时,QGraphicsView还提供了在视图和场景坐标之间进行转换的函数:QGraphicsView::maptosene()和QGraphicsView::mapFromScene()。
在这里插入图片描述

图形项

  QGraphicsItem是场景中图形项的基类。典型的形状的标准图形项有矩形(QGraphicsRectItem)、椭圆(QGraphicsEllipseItem)和文本项(QGraphicsTextItem)等。但只有编写自定义的图形项才能发挥QGraphicsItem的强大功能。

 QGraphicsItem主要支持如下功能:

  • 鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件
  • 键盘输入焦点和键盘事件
  • 拖放事件
  • 碰撞检测

 除此之外,图形项还可以存储自定义的数据,可以使用setData()进行数据存储,然后使用data()获取其中的数据。

 要实现自定义的图形项,那么首先要创建一个QGraphicsItem的子类,然后重新实现它的两个纯虚公共函数:boundingRect()和paint(),前者用来返回要绘制图形项的矩形区域,后者用来执行实际的绘图操作。其中boundingRect()函数将图形项的外部边界定义为一个矩形,所有的绘图操作都必须限制在图形项的边界矩形中。这个矩形对于剔除不可见图形项、确定绘制交叉项目时哪些区域需要重新构建、碰撞检测机制都很重要。一定要保证所有绘图都在boundingRect()的边界之中,特别是当QPainter使用了指定的QPen来渲染图形的边界轮廓时,绘制的图形的边界线的一般会在外面,一半会在里面(例如使用了宽度为两个单位的画笔,就必须在boundingRect()里绘制一个单位的边界线),这也是在boundingRect()中要包含半个画笔宽度的原因。

猜你喜欢

转载自blog.csdn.net/justCJH/article/details/112405169