文章目录
一、Graphics View 框架结构的主要特点
Graphics View 框架结构的主要特点如下。
(1)在 Graphics View 框架结构中,系统可以利用 Qt 绘图系统的反锯齿、OpenGL 工具来改善绘图性能。
(2)Graphics View 支持事件传播体系结构,可以使图元在场景 (scene) 中的交互能力提高 1 倍,图元能够处理键盘事件和鼠标事件。其中,鼠标事件包括鼠标被按下、移动、释放和双击,还可以跟踪鼠标的移动。
(3)在 Graphics View 框架中,通过二元空间划分树 (Binary Space Partitioning, BSP) 提供快速的图元查找,这样就能够实时地显示包含上百万个图元的大场景。
二、Graphics View 框架结构的三元素
Graphics View 框架结构主要包含三个类,即场景类 (QGraphicsScene) 、视图类 (QGraphicsView) 和图元类 (QGraphicsItem),统称为“三元素”。其中,场景类提供了一个用于管理位于其中的众多图元容器,视图类用于显示场景中的图元,一个场景可以通过多个视图表现,一个场景包括多个几何图形。
Graphics View 三元素之间的关系:
2.1 场景类:QGraphicsScene 类
它是一个用于放置图元的容器,本身是不可见的,必须通过与之相连的视图类来显示及与外界进行互操作。通过 QGraphicsScene::addItem() 可以添加一个图元到场景中。图元可以通过多个函数进行检索。QGraphicsScene::items() 和一些重载函数可以返回与点、矩形、多边形或向量路径相交的所有图元。QGraphicsScene::itemAt() 返回指定点的顶层图元。
场景类主要完成的工作包括提供对它包含的图元的操作接口和传递事件、管理各个图元的状态(如选择和焦点处理)、提供无变换的绘制功能(如打印)等。
事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播。如果场景接收了在某一点的鼠标单击事件,场景会将事件传给这一点的图元。
管理各个图元的状态(如选择和焦点处理)。可以通过 QGraphicsScene::setSelectionArea() 函数选择图元,选择区域可以是任意的形状,使用 QPainterPath 表示。若要得到当前选择的图元列表,则可以使用 QGraphicsScene::selectedItems() 函数。可以通过 QGraphicsScene::setFocusItem() 函数或 QGraphicsScene::setFocus() 函数来设置图元的焦点,获得当前具有焦点的图元使用 QGraphicsScene::focusItem() 函数。
如果需要将场景内容绘制到特定的绘图设备,则可以使用 QGraphicsScene::render() 函数在绘图设备上绘制场景。
2.2 视图类:QGraphicsView 类
它提供一个可视的窗口,用于显示场景中的图元。在同一个场景中可以有多个视图,也可以为相同的数据集提供几种不同的视图。
QGraphicsView 是可滚动的窗口部件,可以提供滚动条来浏览大的场景。如果需要使用 OpenGL,则可以使用 QGraphicsView::setViewport() 函数将视图设置为 QGLWidget。
视图接收键盘和鼠标的输入事件,并将它们翻译为场景事件(将坐标转换为场景的坐标)。使用变换矩阵函数 QGraphicsView::matrix() 可以变换场景的坐标,实现场景缩放和旋转。QGraphicsView 提供 QGraphicsView::mapToScene() 和 QGraphicsView::mapFromScene() 函数用于与场景的坐标进行转换。
2.3 图元类:QGraphicsItem 类
它是场景中各个图元的基类,在它的基础上可以继承出各种图元类,Qt 已经预置的包括直线 (QGraphicsLineItem)、椭圆 (QGraphicsEllipseItem)、文本图元 (QGraphicsTextItem)、矩形 (QGraphicsRectItem) 等。当然,也可以在 QGraphicsItem 类的基础上实现自定义的图元类,即用户可以继承 QGraphicsItem 实现符合自己需求的图元。
QGraphicsItem 主要有以下功能。
- 处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件。
- 处理键盘输入事件。
- 处理拖拽事件。
- 分组。
- 碰撞检测。
此外,图元有自己的坐标系统,也提供场景和图元。图元还可以通过 QGraphicsItem::matrix() 函数来进行自身的交换,可以包含子图元。
三、Graphics View 框架结构的坐标系统
Graphics View 坐标基于笛卡儿坐标系,一个图元的场景具有 x 坐标和 y 坐标。当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素。
三个 Graphics View 基本类有各自不同的坐标系,场景坐标、视图坐标和图元坐标。GraphicsView 提供了三个坐标系统之间的转换函数。在绘制图形时,GraphicsView 的场景坐标对应 QPainter 的逻辑坐标、视图坐标和设备坐标。
3.1 场景坐标
场景坐标是所有图元的基础坐标系统。场景坐标系统描述了顶层的图元,每个图元都有场景坐标和相应的包容框。场景坐标的原点在场景中心,坐标原点是 x 轴正方向向右,y 轴正方向向下。
QGraphicsScene 类的坐标系以中心为原点 (0,0) ,如下所示:
3.2 视图坐标
视图坐标是窗口部件的坐标。视图坐标的单位是像素。QGraphicsView 视图的左上角是 (0,0) ,x 轴正方向向右,y 轴正方向向下。所有的鼠标事件最开始都是使用视图坐标。
QGraphicsView 类继承自 QWidget 类,因此它与其他的 QWidget 类一样,以窗口的左上角作为自己坐标系的原点,如下所示:
3.3 图元坐标
图元使用自己的本地坐标,这个坐标系统通常以图元中心为原点,这也是所有变换的原点。图元坐标方向是 x 轴正方向向右,y 轴正方向向下。创建图元后,只需注意图元坐标就可以了,QGraphicsScene 和 QGraphicsView 会完成所有的变换。
QGraphicsItem 类的坐标系,在调用 QGraphicsItem 类的 paint() 函数重绘图元时,则以此坐标系为基准,如下所示:
形式 1 :
形式 2 :
根据需要,Qt 提供了这三个坐标系之间的互相转换函数,以及图元与图元之间的转换函数,若需从 QGraphicsItem 坐标系中的某一点坐标转换到场景中的坐标,则可调用 QGraphicsItem 的 mapToScene() 函数进行映射。而 QGraphicsItem 的 maoToParent() 函数则可将 QGraphicsItem 坐标系中的某点坐标映射至它的上一级坐标系中,有可能是场景坐标,也有可能是另一个 QGraphicsItem 坐标。
Graphics View 框架提供了多种坐标变换函数,
映射函数 | 转换类型 |
---|---|
QGrahicsView::mapToScene() | 从视图到场景 |
QGraphicsView::mapFromScene() | 从场景到视图 |
QGraphicsItem::mapToSecne() | 从图元到场景 |
QGraphicsItem::mapFromScene() | 从场景到图元 |
QGraphicsItem::mapToParent() | 从子图元到父图元 |
QGraphicsItem::mapFromParent() | 从父图元到子图元 |
QGraphicsItem::mapToItem() | 从本图元到其他图元 |
QGraphicsItem::mapFromItem() | 从其他图元到本图元 |