type
status
date
slug
summary
tags
category
icon
password
Email
落絮无声春堕泪,行云有影月含羞。——吴文英《浣溪沙》
文章首发于我的个人博客:欢迎大佬们来逛逛
Qt学习的项目地址源码:
Qt-code
luumod • Updated Jul 3, 2023
图形视图框架
图形视图提供了一个界面,用于管理大量定制的2D图形项并与之交互,还提供了一个视图小部件,用于可视化这些项,支持缩放和旋转。
该框架包括一个事件传播体系结构,允许对场景中的项目进行精确的双精度交互功能。项目可以处理按键事件、鼠标按下、移动、释放和双击事件,还可以跟踪鼠标移动。
GraphicsView使用BSP(二进制空间分区)树来提供非常快速的项目发现,因此,它可以实时可视化大型场景,即使有数百万个项目。
场景Scene
QGraphicsScene
提供了图形视图场景。通过以下方式可以创建一个场景:
我们需要指定场景的 坐标以及 等属性,注意这四个表示场景的显示区域。
QGraphicsScene管理某些项目状态,比如项目选择和焦点。
你可以通过调用
QGraphicsScene::setSelectionArea()
来选择场景中的项目,传递一个任意形状。调用QGraphicsScene::selectedItems()获取当前所有选中项的列表。
视图View
QGraphicsView
提供了视图小部件,它可视化了场景的内容。可以把场景添加到视图中。
您可以将多个视图附加到同一个场景,从而为相同的数据集提供多个视口。
当创建完成视图和场景后,可以使用场景构造函数的最后一个参数:QObject来传递一个依赖视图。
也可以使用视图的
setScene
来为视图设置一个场景。最后调用
show
即可显示视图。要记住:显示的是视图(用show方法),只不过这个视图上包含了这个场景。
为这个场景或者视图添加装饰:
- setBackgroundBrush:设置背景画刷,传递一个QBrush类型的参数
- setForegroundBrush:设置前景画刷,前景位于最前面,因此它会覆盖背景的画刷,可以指定一个透明度,这样就会呈现一个昏暗的效果,类似于夜间模式。
首先我们加一下背景颜色:然后我们再指定一下前景色,并且设置透明度
可以看到背景色会覆盖之前的背景色,前景色会覆盖背景色。
请注意:我们即可以对场景设置上面的属性,也可以对视图设置。
如果我们对视图设置,并且如果许多视图都加载同一个场景,则会发现只有设置的视图才会显示上面的效果;
如果我们对场景设置,则所有设置该场景的视图都被显示为上面的效果。
图形项Item
QGraphicsItem
是场景中图形项的基类。图形视图为典型形状提供了几个标准项,例如- 矩形(QGraphicsRectItem)
- 椭圆(QGraphicsEllipseItem)
- 文本项(QGraphicsTextItem)
但最强大的QGraphicsItem特性是在编写自定义项时可用的。除此之外,QGraphicsItem支持以下特性:
- 鼠标按下、移动、释放和双击事件,以及鼠标悬停事件、滚轮事件和上下文菜单事件。
- 键盘输入焦点和按键事件
- 拖放
- 通过父子关系和QGraphicsItemGroup进行分组
- 碰撞检测
item存在于本地坐标系统中,像QGraphicsView一样,它还提供了许多函数来映射项目和场景之间的坐标,以及项与项之间的坐标。
同样,像QGraphicsView一样,它可以使用矩阵:QGraphicsItem::transform()转换其坐标系统。这对于旋转和缩放单个项目非常有用。
常用API:
- QGraphicsItem::collidesWith:两个项目的碰撞检测
- mapFrom/ToXXXX:各种坐标的映射到那些地方
- setPos,Pos,moveBy:Item的移动操作
图形视图框架中的类
类 | 描述 |
QAbstractGraphicsShapeltem | 所有路径图元的共同基类 |
QGraphicsAnchor | 表示一个QGraphicsAnchorLayout中两个图元之间的anchor |
QGraphicsAnchorLayout | 布局可以anchor部件到图形视图中 |
QGraphicsEffect | 所有图形特效的基类 |
QGraphicsEllipseltem | 可以添加到QGraphicsScene的椭圆图元 |
QGraphicsGridLayout | 图形视图中管理部件的网格布局 |
QGraphicsltem | QGraphicsScene中所有图元的基类 |
QGraphicsltemGroup | —个将图元组当做单个图元来看待的容器 |
QGraphicsLayout | 图形视图中所有布局类的基类 |
QGraphicsLayoutltem | 可以被继承,允许布局类管理的自定义图元 |
QGraphicsLineltem | 可以添加到QGraphicsScene的直线图元 |
QGraphicsLinearLayout | 图形视图中管理部件的水平或垂直布局 |
QGraphicsObject | 所有需要信号、槽、属性的图元的基类 |
QGraphicsPathltem | 可以添加到QGraphicsScene的路径图元 |
QGraphicsPixmapltem | 可以添加到QGraphicsScene的图形图元 |
QGraphicsPolygonltem | 可以添加到QGraphicsScene的多边形图元 |
QGraphicsProxyWidget | 代理,用于将一个QWidget对象嵌入到QGraphicsScene中 |
QGraphicsRectltem | 可以添加到QGraphicsScene的矩形图元 |
QGraphicsScene | 管理大量2D图元的管理器 |
QGraphicsSceneContextMenuEvent | 图形视图框架中的上下文菜单事件 |
QGraphicsSceneDragDropEvent | 图形视图框架中的拖放事件 |
QGraphicsSceneEvent | 所有图形视图相关事件的基类 |
QGraphicsSceneHelpEvent | Tooltip请求时的事件 |
QGraphicsSceneHoverEvent | 图形视图框架中的悬停事件 |
QGraphicsSceneMouseEvent | 图形视图框架中的鼠标事件 |
QGraphicsSceneMoveEvent | 图形视图框架中的部件移动事件 |
QGraphicsSceneResizeEvent | 图形视图框架中的部件大小改变事件 |
QGraphicsSceneWheelEvent | 图形视图框架中的鼠标滚轮事件 |
QGraphicsSimpleTextltem | 可以添加到QGraphicsScene的简单文本图元 |
QGraphicsSvgltem | 可以用来呈现SVG文件内容的QGraphicsltem |
GraphicsTextltem | 可以添加到QGraphicsScene的文本图元,用于显示格式化文本 |
QGraphicsTransform | 创建QGraphicsltems高级矩阵变换的抽象基类 |
QGraphicsView | 显示一个QGraphicsScene内容的部件 |
QGraphicsWidget | QGraphicsScene中所有部件图元的基类 |
QStyleOptionGraphicsltem | 用于描述绘制一个QGraphicsltem所需的参数 |
图形视图坐标系统
图形视图基于笛卡尔坐标系;道具在场景中的位置和几何形状由两组数字表示:x坐标和y坐标。当使用未转换视图观察场景时,场景中的一个单元由屏幕上的一个像素表示。
在图形视图中有三种有效的坐标系统:item坐标、scene坐标和view坐标。
为了简化实现,Graphics View提供了方便的函数,允许您在三个坐标系统之间进行映射。
渲染时,图形视图的场景坐标对应于QPainter的逻辑坐标,视图坐标与设备坐标相同。在坐标系统文档中,您可以了解逻辑坐标和设备坐标之间的关系。
场景坐标
场景表示所有项目的基本坐标系统。场景坐标系统描述了每个顶级项目的位置,也形成了从视图传递到场景的所有场景事件的基础。场景中的每个项目都有一个场景位置和边界矩形(QGraphicsItem::scenePos(), QGraphicsItem::sceneBoundingRect()),除了它的本地项目pos和边界矩形。场景坐标描述了项目在场景坐标中的位置,它的场景边界矩形构成了QGraphicsScene如何确定场景中哪些区域发生了变化的基础。场景中的变化是通过QGraphicsScene::changed()信号传递的,参数是一个场景矩形列表。
视图坐标
视图坐标是Widget的坐标。视图坐标中的每个单元对应一个像素。这个坐标系的特殊之处在于它相对于小部件或视口,不受所观察场景的影响。QGraphicsView的viewport的左上角总是(0,0),右下角总是(viewport width, viewport height)。所有鼠标事件和拖放事件最初都是作为视图坐标接收的,为了与项目交互,您需要将这些坐标映射到场景。
坐标映射及案例
通常在处理场景中的项目时,将坐标和任意形状从场景映射到项目,从项目映射到项目,或从视图映射到场景是很有用的。
当你在QGraphicsView中点击鼠标时,询问场景光标下的项目是什么:
- 你可以通过调用QGraphicsView::mapToScene()
- 然后再调用QGraphicsScene::itemAt()
如果你想知道一个项目Item在View中的位置:
- 你可以在项目上调用QGraphicsItem::scenePos()
- 然后在视图上调用QGraphicsView::mapFromScene()。
最后,如果你想要找到视图某区域内的所有项目:
- 你可以传递一个
QPainterPath
给QGraphicsScene::mapToScene()
- 然后传递映射路径给QGraphicsScene::items()。
你可以通过调用QGraphicsItem::mapToScene()和QGraphicsItem::mapFromScene()将坐标和形状映射到项目的场景或者从场景映射。
你也可以通过调用QGraphicsItem:: maptopparent()和QGraphicsItem::mapFromParent()映射到一个项目的父项目,或者通过调用QGraphicsItem::mapToItem()和QGraphicsItem::mapFromItem()映射到项目之间。
所有的映射函数都可以映射点、矩形、多边形和路径。
视图中也有相同的映射函数,用于从场景映射到场景。QGraphicsView::mapFromScene()和QGraphicsView::mapToScene()。要从视图映射到项,首先映射到场景,然后从场景映射到项。
映射函数 | 描述 |
QGraphicsView::mapToScene() | 从视图坐标系统映射到场景坐标系统 |
QGraphicsView::mapFromScene() | 从场景坐标系统映射到视图坐标系统 |
QGraphicsItem::mapToScene() | 从图形项的坐标系统映射到场景的坐标系统 |
QGraphicsItem::mapFromScene() | 从场景的坐标系统映射到图形项的坐标系统 |
QGraphicsItem::mapToParent() | 从本图形的坐标系统映射到其父图形的坐标系统 |
QGraphicsItem::mapFromParent() | 从父图形项的坐标系统映射到本图形项的坐标系统 |
QGraphicsItem::mapToItem() | 从本图形项的坐标系统映射到另一个图形项的坐标系统 |
QGraphicsItem::mapFromScene() | 从另一个图形项的坐标系统映射到本图形项的坐标系统 |
其他属性
缩放和旋转
QGraphicsView具有的对视图的操作:
- scale:缩放
- rotate:旋转
拖放
因为QGraphicsView间接继承了QWidget,所以它已经提供了与QWidget相同的拖放功能。此外,为了方便起见,图形视图框架为场景和每个项目提供了拖放支持。
当视图接收到拖拽时,它将拖放事件转换为QGraphicsSceneDragDropEvent,然后将其转发到场景。场景接管了这个事件的调度,并将其发送到鼠标光标下接受掉落的第一个项目。
要从一个项目开始拖动,创建一个QDrag对象,将一个指针传递给开始拖动的小部件。项目可以被多个视图同时观察,但只有一个视图可以开始拖动。在大多数情况下,拖动是由于按下或移动鼠标而开始的,因此在mousePressEvent()或mouseMoveEvent()中,您可以从事件中获得原始小部件指针。例如:
为了拦截场景的拖放事件,你在一个QGraphicsItem子类中重新实现QGraphicsScene::dragEnterEvent()和任何你特定场景需要的事件处理程序。您可以在QGraphicsScene的每个事件处理程序的文档中阅读更多关于图形视图中拖放的信息。
项目可以通过调用QGraphicsItem::setAcceptDrops()来启用拖放支持。要处理传入的拖动,重新实现QGraphicsItem::dragEnterEvent(), QGraphicsItem::dragMoveEvent(), QGraphicsItem::dragLeaveEvent()和QGraphicsItem::dropEvent()。
- 作者:Yuleo
- 链接:https://www.helloylh.com/article/qt18
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。