QT(15):Graphics View框架

Graphics View框架:

Graphics View提供了一个用于管理和与大量自定义 2D 图形项目交互的界面,以及一个用于可视化项目的view widget,并支持缩放和旋转。

该框架包括一个事件传播架构,允许对场景中的项目进行精确的双精度交互功能。项目可以处理关键事件、鼠标按下、移动、释放和双击事件,还可以跟踪鼠标移动。

Graphics View使用BSP(二进制空间分区)树来提供非常快速的项目查找,因此,它可以实时可视化大型场景,即使有数百万个项目。

Graphics View在Qt 4.2中引入,取代了其前身QCanvas。

Graphics View体系结构

Graphics View提供了一种基于项目的“模型-视图”编程方法,很像InterView的QTableView, QTreeView and QListView。多个视图可以观察单个场景,并且该场景包含不同几何形状的项目。

1.场景:
QGraphicsScene提供图形视图场景。场景具有以下职责:

  • 提供用于管理大量项目的快速界面
  • 将事件传播到每个项目
  • 管理项目状态,例如选择和焦点处理
  • 提供未转换的渲染功能,主要用于印刷

场景充当QGraphicsItem对象的容器。通过调用QGraphicsScene::addItem()将项添加到场景中,然后通过调用多个项发现函数之一进行检索。QGraphicsScene::items()及其重载返回指定点、矩形、多边形或常规矢量路径包含或与之相交的所有项。QGraphicsScene::itemAt()返回特定点的最顶层项。所有项目查找函数都按降序堆叠顺序返回项目(即,第一个返回的项目是最顶层的,最后一个项目是最底部的)。

QGraphicsScene的事件传播体系结构将场景事件传递到项目,并管理项目之间的传播。如果场景在特定位置收到鼠标按下事件,则场景会将事件传递给位于该位置的任何项目。

QGraphicsScene还管理某些项目状态,例如项目选择和焦点。您可以通过调用 QGraphicsScene::setSelectionArea()来选择场景中的项,参数传递任意形状。此功能还用作QGraphicsView中橡皮筋选择的基础。QGraphicsScene::selectedItems()获取所有当前选定项的列表。处理的另一个状态是项目是否具有键盘输入焦点。您可以通过调用QGraphicsScene::setFocusItem()或者QGraphicsItem::setFocus()来设置项目焦点,可以通过调用QGraphicsScene::focusItem()来获取当前焦点项目。

最后,QGraphicsScene允许通过QGraphicsScene::render()函数将场景的某些部分渲染到绘画设备中。

2.视图
提供view widget,用于可视化场景的内容。可以将多个视图附加到同一场景,以便在同一数据集中提供多个viewport。view widget是一个滚动区域,并提供用于在大型场景中导航的滚动条。要启用 OpenGL 支持,您可以通过调用setViewport将一个QOpenGLWidget对象设置为视口。

视图从键盘和鼠标接收输入事件,并将这些事件转换为场景事件(在适当的情况下将使用的坐标转换为场景坐标),然后再将事件发送到可视化场景。

使用其变换矩阵QGraphicsView::transform(),视图可以变换场景的坐标系。这允许高级导航功能,例如缩放和旋转。为方便起见,还提供了在视图和场景坐标之间转换的功能:QGraphicsView::mapToScene() and QGraphicsView::mapFromScene()。

3.项目
是场景中图形项的基类。图形视图为典型形状提供了多个标准项,例如矩形、椭圆和文本项,但在编写自定义项时可以使用最强大的功能。此外,还支持以下功能:

鼠标按下、移动、释放和双击事件,以及鼠标悬停事件、滚轮事件和上下文菜单事件。
键盘输入焦点和键事件
拖放
分组
碰撞检测

项目位于局部坐标系中,与QGraphicsView一样,提供了许多函数,用于在项目和场景之间以及项目之间映射坐标。此外,像QGraphicsView一样,它可以使用矩阵QGraphicsItem::transform()转换其坐标系。这对于旋转和缩放单个项目很有用。

项目可以包含其他项目(子项)。父项的转换由其所有子项继承。但是,无论项目的累积转换如何,它的所有函数(例如 QGraphicsItem::contains(), QGraphicsItem::boundingRect(), QGraphicsItem::collidesWith())仍然在本地坐标中运行。

QGraphicsItem通过QGraphicsItem::shape()函数和 QGraphicsItem::collidesWith()支持碰撞检测,两者都是虚函数。通过将项目的形状作为局部坐标从QGraphicsItem::shape()返回,QGraphicsItem将处理所有碰撞检测。但是,如果要提供自己的碰撞检测,则可以重新实现QGraphicsItem::collidesWith()。

Graphics View坐标系

Graphics View基于笛卡尔坐标系,项目在场景中的位置和几何图形由两组数字表示:X 坐标和 Y 坐标。使用未变换的视图观察场景时,场景上的一个单元由屏幕上的一个像素表示。

Graphics View中有三种有效的坐标系:项目坐标、场景坐标和视图坐标。为了简化实现,Graphics View提供了方便的功能,允许您在三个坐标系之间进行映射。

渲染时,Graphics View的场景坐标对应于QPainter的逻辑坐标,视图坐标与设备坐标相同。

项目坐标
项目位于其自己的局部坐标系中。它们的坐标通常以中心点(0,0)为中心,这也是所有变换的中心。项目坐标系中的几何基元通常称为项目点、项目线或项目矩形。

创建自定义项目时,只需注意项目坐标,QGraphicsScene and QGraphicsView执行所有转换。这使得实现自定义项变得非常容易。例如,如果收到鼠标按下或拖动输入事件,则事件位置以项目坐标给出。如果某个点在项目内,QGraphicsItem::contains()则返回true,否则返回 false,在项目坐标中获取点参数。同样,项目的边界矩形和形状位于项目坐标中。

项目位置是在其父坐标系中 “项目的中心点” 的坐标,有时称为父坐标。从这个意义上说,场景被视为所有无父母项目的“父母”。顶级项目的位置位于场景坐标中。

子坐标和父坐标有关。如果子坐标未变换,则子坐标和父坐标之间的差异与父坐标中项目之间的距离相同。例如:如果未转换的子项精确定位在其父项的中心点,则这两个项的坐标系将相同。但是,如果子项的位置是(10,0),则子项的(0,10)点将对应于其父项的(10,10)点。

由于项的位置和转换相对于父项,因此子项的坐标不受父项转换的影响,尽管父项的转换隐式变换了子项。在上面的示例中,即使父级旋转和缩放,子项的(0,10)点仍将对应于父项的(10,10)点。然而,相对于场景,孩子将跟随父母的转变和位置。如果父项缩放(2x, 2x),则子项的位置将位于场景坐标(20,0),其(10,0)点将与场景中的点 (40,0)相对应。

除了QGraphicsItem::pos()是少数例外之一,QGraphicsItem的函数在项坐标中运行,而不管项或其父项的任何转换。例如,项目的边界矩形(即QGraphicsItem::boundingRect())始终以项目坐标给出。

场景坐标
场景表示其所有项目的基本坐标系。场景坐标系描述每个顶级项目的位置,也构成了从视图传递到场景的所有场景事件的基础。 场景中的每个项目都有一个场景位置和边界矩形(QGraphicsItem::scenePos(), QGraphicsItem::sceneBoundingRect()),此外还有其本地坐标的 pos 和边界矩形。场景位置描述项目在场景坐标中的位置,其场景边界矩形构成了如何确定场景的哪些区域已更改的基础。场景中的更改通过QGraphicsScene::changed()信号进行通信,参数是已更改区域的场景矩形的列表。

视图坐标
视图坐标是widget的坐标。视图坐标中的每个单位对应一个像素。此坐标系的特别之处在于它相对于widget或viewport,并且不受观察场景的影响。QGraphicsView的左上角始终为(0,0),右下角始终为(视口宽度、视口高度)。所有鼠标事件和拖放事件最初都是作为视图坐标接收的,需要将这些坐标映射到场景才能与项目进行交互。

主要特点

缩放和旋转
支持与通过 QGraphicsView::setMatrix()相同的仿射变换。通过对视图应用转换,您可以轻松添加对常见功能(如缩放和旋转)的支持。

印刷
GraphicsView通过其渲染函数QGraphicsScene::render()和QGraphicsView::render()提供单行打印。这些函数提供相同的 API:通过将QPainter传递给任一呈现函数,可以让场景或视图将其全部或部分内容渲染到任何绘制设备中。
场景渲染函数和视图渲染函数之间的区别在于,一个在场景坐标中运行,另一个在视图坐标中运行。QGraphicsScene::render()通常是打印未转换场景的整个段的首选,例如打印几何数据或打印文本文档。另一方面,QGraphicsView::render()适合截图,其默认行为是使用提供的绘制器渲染viewport的确切内容。

当源区域和目标区域的大小不匹配时,源内容将被拉伸以适合目标区域。通过将Qt::AspectRatioMode传递给您正在使用的渲染函数,您可以选择在拉伸内容时保持或忽略场景的纵横比。

拖放
由于QGraphicsView间接继承widget,因此它已提供与widget提供相同的拖放功能。此外,为了方便起见,图形视图框架为场景和每个项目提供了拖放支持。当视图收到拖动时,它会将拖放事件转换为QGraphicsSceneDragDropEvent,然后将其转发到场景。场景接管此事件,并将其发送到鼠标光标下接受拖放的第一项。

要从项目开始拖动,需要创建一个QDrag对象,并将指针传递给启动拖动的widget。多个视图可以同时监控项目,但只有一个视图可以开始拖动。在大多数情况下,拖动是通过按下或移动鼠标而开始的,因此在mousePressEvent()或mouseMoveEvent()中,您可以从事件中获取原始widget指针。

要截获场景的拖放事件,请在QGraphicsItem子类中重新实现特定场景所需的任何事件处理程序和QGraphicsScene::dragEnterEvent()。

项目可以通过调用QGraphicsItem::setAcceptDrops()来启用拖放支持。要处理传入的拖动,请重新实现QGraphicsItem::dragEnterEvent(),QGraphicsItem::dragMoveEvent(),QGraphicsItem::dragLeaveEvent(),and QGraphicsItem::dropEvent()。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值