文章目录
一、Graphics View框架结构特点
(1)在Graphics View框架结构中,可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能。
(2)Graphics View支持事件传播体系结构,可以使用图元在场景(Scene)中的交互能力提高1倍,图元能够处理键盘事件和鼠标事件。
(3)在Graphics View框架中,通过二元空间划分树(Binary Space partitioning,BSP)提供快速的图元查找,能够实时地显示包含上百万个图元的大场景。
二、图形视图框架的结构
图形视图框架包括场景(Scene)、视图(View)、图形项(GraphicsItem)三部分。三部分用QGraphicsScene、QGraphicsView和QGraphicsItem三个类来表示。
(1)场景类:QGraphicsScene类
QGraphicsScene是一个放置图元的容器,是图形视图框架中的场景,拥有以下功能:
1、提供用于管理大量图形项(Items)的便捷接口。
2、分发事件给场景中的每一个图形项。
3、管理图形项(items)的状态,例如:选择和焦点处理等。
4、提供无变换的渲染功能,主要用于打印。
场景是图形项QGraphicsItem对象的容器。调用QGraphicsScene::addItem()函数将图形项(Items)添加到场景中,然后调用众多的图形项查找函数来检索添加的图形项。
QGraphicsScene::items()函数和几个重载函数可以返回符合条件的所有图形项,这些图形项不是与指定的点、矩形、多边形或者矢量路径相交,就是包含在它们之中。
QGraphicsScene::itemAt()函数返回指定点的最上面的图形项(场景中的图形项可能会重叠)。所有的图形项寻找函数返回的图形项都是按照递减顺序进行的(例如第一个返回的图形项在最上面,最后返回的图形项在最下面)。
如果要从场景中删除一个图形项,可以使用QGraphicsScene::RemoveItem()函数。
场景允许通过QGraphicsScence::render()函数将场景的各个部分呈现到一个绘制设备中。
(1)视图类:QGraphicsView类
用于显示场景中的图元
QGraphicsView提供了视图widget,用来显示场景中的内容。可以将多个视图连接到同一个场景来为相同的数据集提供多个视口。
QGraphicsView是一个可滚动的区域控件,提供了一个滚动条来浏览大的场景,可以使用setDragMode()函数以QGraphicsView::ScrollHandDrag为参数来使光标变为手掌形状,从而可以拖动场景。如果设置setDragMode()的参数为QGraphicsView::RubberBandDrag,那么可以在视图上使用鼠标拖出橡皮筋框来选择图形项。
视图从键盘和鼠标接收输入事件,并将其转换成场景事件(在适当的地方将使用的坐标转换为场景坐标),然后将事件发送到可视化场景。
使用QGraphicsView::transform(),视图可以转换场景的坐标系统。同样提供了转换视图和场景坐标的功能:QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()。
默认的QGraphicsView提供了一个QWidget作为视口部件,如果要使用OpenGL进行渲染,可以调用QGraphicsView::setViewport()设置QGLWidget作为视口。QGraphicsView会获取视口部件的拥有权(ownership)。
(2)图元类:QGraphicsItem类
QGraphicsItem是场景中图形项的基类。图形视图框架为常见的典型形状提供了标准的图形项,例如:矩形(QGraphicsRectIem)、椭圆(QGraphicsEllipseItem)和文本项(QGraphicsTextItem)等。不过,只有当编写自定义图形项时才能发挥QGraphicsItem的强大功能。QGraphicsItem主要支持如下功能:
1、鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件
2、键盘输入焦点和键盘事件
3、拖放事件
4、分组,使用QGraphicsItemGroup通过parent-child关系来实现
5、碰撞检测
除此之外,图形项还可以存储自定义的数据,可以使用setData()进行数据存储,然后使用data()获取其中的数据。
一个场景分为三层:图形项层(ItemLayer)、前景层(ForegroundLayer)和背景层(BackgroundLayer)。场景的绘制总是从背景层开始,然后是图形项层,最后是前景层。前景层和背景层都可以使用QBrush进行填充,比如使用渐变和贴图等。这里的前景色设置为了半透明的白色,当然也可以设置为其他的填充。
三、图形视图框架的坐标系统
图形视图是基于笛卡尔坐标系统的。
三个图形视图框架的基本类有各自不同的坐标系:场景坐标、视图坐标和图元坐标。
在渲染时,图形视图的场景坐标对应于QPainter的逻辑坐标,视图坐标与设备坐标相同。
(3-1)场景坐标
场景坐标是所有图元的基础坐标系统。场景坐标的原点在场景中心。QGraphicsScene类的坐标系以中心为原点(0,0)。
场景中的每个项目都有一个场景位置和边界矩形(QGraphicsItem::scenePos(),QGraphicsItem::sceneBoundingRect())。此外还有它的本地项目pos和边界矩形。场景位置描述了项目在场景坐标中的位置,其场景边界矩形构成了QGraphicsScene如何确定场景中哪些区域发生了变化的基础。场景中的变化通过QGraphicsScene::changed()信号进行通信,参数为场景矩形列表。
(3-2)视图坐标
视图坐标是窗口部件的坐标。视图坐标的单位是像素。QGraphicsView视图的左上角是(0,0)。QGraphicsView类继承自Qwidget类,所以该类以窗口的左上角作为自己坐标系的原点。QGraphicsView的viewport的左上角总是(0,0),而右下角总是(viewport.width,viewport height)。所有鼠标事件和拖放事件最开始时都是作为视图坐标接收,在使用中需要将这些坐标映射到场景以与图元交互。
(3-3)图元坐标
图元使用自己的本地坐标,这个坐标系统通常以图元中心为原点。
在创建自定义图形项(Item)时,我们只需要关心图元坐标。
四、类关系
五、类图
(5-1)图形效果类图
(5-2)图形布局类图
(5-3)图形项类图
六、图形视图框架的事件处理与传播
图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景传递给相应的图形项。即:
视图——>场景——>图形项
(1)对于键盘事件,它会传递给获得焦点的图形项,可以使用QGraphicsScene类的setFocusItem()函数或者图形项自身调用setFocus()函数来将其设置为焦点图形项。默认情况下,如果场景没有获得焦点,那么所有的键盘事件都会被丢弃。如果调用了场景的setFocus()函数或者场景中的一个图形项获得了焦点,那么场景也会自动获得焦点。
(2)对于鼠标悬停效果,QGraphicsScene会调度悬停事件。如果一个图形项可以接收悬停事件,那么当鼠标进入它的区域之中时,它就会收到一个GraphicsSceneHoverEnter事件。如果鼠标继续在图形项的区域之中进行移动,那么QGraphicsScene就会向该图形项发送GraphicsSceneHoverMove事件。当鼠标离开图形项的区域时,它将会收到一个GraphicsSceneHoverLeave事件。图形项默认是无法接收悬停事件的,可以使用QGraphicsItem类的setAcceptHoverEvents()函数设置图形项接收鼠标悬停事件。
七、总结
文本总结了Qt中的图形视图框架的基础知识,包括常用类、类图关系、图形视图框架的图标系统以及图形视图框架的事件处理和传播。
搜索关注【嵌入式小生】wx公众号获取更多精彩内容。