图形视图(01):【纲】Graphics View Framework [官翻]

文章目录

  • 图形视图体系结构
    • 场景
    • 视图
    • 项目
  • 图形视图框架中的类
  • 图形视图的坐标系
    • 项目坐标
    • 场景坐标
    • 视图坐标
    • 坐标映射
  • 主要特点
    • 缩放和旋转
    • 打印
    • 拖放
    • 光标和工具提示
    • 动画
    • OpenGL渲染
    • 项目组
    • 小部件和布局
      • QGraphicsWidget
      • QGraphicsLayout
    • 嵌入式小部件支持
  • 性能
    • 浮点指令
  • 参考

Graphics View Framework

图形视图提供了一个用于管理大量定制的二维图形项目并与之交互的界面,以及一个用于可视化项目的视图小部件,并支持缩放和旋转。

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

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

图形视图是在Qt 4.2中引入的,取代了它的前身QCanvas。

图形视图体系结构

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

场景

QGraphicsScene图形视图场景。现场承担以下职责:

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

该场景用作QGraphicsItem对象的 容器。 通过调用QGraphicsScene::addItem() 将项目添加到场景中,然后通过调用许多项目发现功能之一来检索项目。 QGraphicsScene::items() 及其重载返回由点,矩形,多边形或常规矢量路径包含或与之相交的所有项目。 QGraphicsScene::itemAt() 返回特定点上的最高项目。 所有项目发现功能均以降序堆叠的方式返回项目(即,第一个返回的项目是最上面的,而最后一个项目是最底部的) 。

QGraphicsScene的事件传播架构可安排场景事件以交付给项目,并管理项目之间的传播。如果场景在某个位置收到鼠标按下事件,则场景会将事件传递到该位置上的任何项目。

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

最后,QGraphicsScene允许您通过QGraphicsScene::render() 函数将场景的一部分渲染到绘制设备中。您可以在本文档后面的“打印”部分中了解有关此内容的更多信息。

视图

QGraphicsView提供了视图小部件,该部件可将场景的内容可视化。 您可以将多个视图附加到同一场景,以在同一数据集中提供多个视口。 视图小部件是一个滚动区域,并提供用于在大型场景中导航的滚动条。 要启用OpenGL支持,可以通过调用QGraphicsView::setViewport() 将QOpenGLWidget设置为视口。

该视图从键盘和鼠标接收输入事件,并将其转换为场景事件(在适当的情况下,将事件发送到可视化场景之前将其转换为场景坐标) 。

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

img

图形视图框架中的类

这些类提供了用于创建交互式应用程序的框架。

图形视图(01):【纲】Graphics View Framework [官翻]
class Description
QAbstractGraphicsShapeItem 所有路径项目的共同基础
QGraphicsAnchor 表示QGraphicsAnchorLayout中两个项目之间的锚点
QGraphicsAnchorLayout 可以在“图形视图”中将小部件固定在一起的布局
QGraphicsEffect 所有图形效果的基类
QGraphicsEllipseItem 可以添加到QGraphicsScene的椭圆项
QGraphicsGridLayout 用于在“图形视图”中管理小部件的网格布局
QGraphicsItem QGraphicsScene中所有图形项的基类
QGraphicsItemGroup 将一组项目视为单个项目的容器
QGraphicsLayout 图形视图中所有布局的基类
QGraphicsLayoutItem 可以继承以允许您的自定义项目由布局管理
QGraphicsLineItem 您可以添加到QGraphicsScene的订单项
QGraphicsLinearLayout 用于在“图形视图”中管理小部件的水平或垂直布局
QGraphicsObject 所有需要信号,插槽和属性的图形项的基类
QGraphicsPathItem 可以添加到QGraphicsScene的路径项
QGraphicsPixmapItem 可以添加到QGraphicsScene的Pixmap项
QGraphicsPolygonItem 您可以添加到QGraphicsScene的多边形项目
QGraphicsProxyWidget 用于将QWidget嵌入QGraphicsScene的代理层
QGraphicsRectItem 可以添加到QGraphicsScene的矩形项目
QGraphicsScene 用于管理大量2D图形项目的表面
QGraphicsSceneContextMenuEvent 图形视图框架中的上下文菜单事件
QGraphicsSceneDragDropEvent 图形视图框架中的拖放事件
QGraphicsSceneEvent 所有图形视图相关事件的基类
QGraphicsSceneHelpEvent 请求工具提示时的事件
QGraphicsSceneHoverEvent 在图形视图框架中悬停事件
QGraphicsSceneMouseEvent 图形视图框架中的鼠标事件
QGraphicsSceneMoveEvent 在图形视图框架中移动小部件的事件
QGraphicsSceneResizeEvent 在图形视图框架中调整窗口小部件大小的事件
QGraphicsSceneWheelEvent 图形视图框架中的Wheel事件
QGraphicsSimpleTextItem 您可以添加到QGraphicsScene的简单文本路径项
QGraphicsSvgItem 可用于呈现SVG文件内容的QGraphicsItem
QGraphicsTextItem 可以添加到QGraphicsScene以显示格式化文本的文本项
QGraphicsTransform 用于在QGraphicsItems上构建高级转换的抽象基类
QGraphicsView 用于显示QGraphicsScene内容的小部件
QGraphicsWidget QGraphicsScene中所有小部件项目的基类
QStyleOptionGraphicsItem 用于描述绘制QGraphicsItem所需的参数

图形视图的坐标系

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

注意:由于“图形视图”使用Qt的坐标系,因此不支持反转的Y轴坐标系(其中y向上增长) 。

图形视图中有三个有效的坐标系统在起作用:项目坐标场景坐标视图坐标。 为了简化您的实现,“图形视图”提供了方便的功能,使您可以在三个坐标系之间进行映射。

渲染时,“图形视图”的场景坐标对应于QPainter的逻辑坐标,并且视图坐标与设备坐标相同。 在坐标系统文档中,您可以阅读有关逻辑坐标和设备坐标之间的关系的信息。

img

项目坐标

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

创建自定义项目时,只需要担心项目坐标; QGraphicsScene和QGraphicsView将为您执行所有转换。这使得实现自定义项非常容易。例如,如果收到鼠标按下或拖动输入事件,则事件位置以项目坐标给出。 QGraphicsItem::contains() 虚函数,如果某个点在您的项内,则返回true,否则返回false,在项坐标中采用point参数。类似地,项目的边界矩形和形状都在项目坐标中。

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

子坐标是相对于父坐标的。如果子对象未变形,则子坐标与父坐标之间的差异与父坐标中各项之间的距离相同。例如:如果未变换的子项正好位于其父项的中心点,则两个项的坐标系将相同。但是,如果孩子的位置是(10,0) ,则孩子的(0,10) 点将与其父级的(10,10) 点相对应。

因为项的位置和变换是相对于父项的,所以子项的坐标不受父项变换的影响,尽管父项的变换会隐式地变换子项。在上面的示例中,即使旋转父级和缩放父级,子级(0,10) 的点仍将对应于父级(10,10) 的点。但是,相对于场景,孩子将遵循父对象的变换和位置。如果将父级缩放(2x,2x) ,则子级的位置将在场景坐标(20,0) 处,并且其(10,0) 点将与场景上的点(40,0) 相对应。

由于QGraphicsItem::pos() 是少数例外之一,因此QGraphicsItem的函数在项目坐标中操作,而与项目或其父项转换无关。例如,项目的边界矩形(即QGraphicsItem::boundingRect() ) 始终在项目坐标中给出。

场景坐标

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

视图坐标

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

坐标映射

通常,在处理场景中的项目时,将场景中的坐标和任意形状映射到项目,项目到项目或视图到场景会很有用。例如,当您在QGraphicsView的视口中单击鼠标时,可以通过调用QGraphicsView::mapToScene() ,然后是QGraphicsScene::itemAt() 来询问场景光标下方是什么项目。如果您想知道某个项目在视口中的位置,可以在该项目上调用QGraphicsItem::mapToScene() ,然后在视图上调用QGraphicsView::mapFromScene() 。最后,如果要查找椭圆形内的项目,可以将QPainterPath传递给mapToScene() ,然后将映射的路径传递给QGraphicsScene::items() 。

您可以通过调用QGraphicsItem::mapToScene() 和QGraphicsItem::mapFromScene() 在项目场景之间来回映射坐标和形状。您还可以通过调用QGraphicsItem::mapToParent() 和QGraphicsItem::mapFromParent() 映射到项目的父项,或者通过调用QGraphicsItem::mapToItem() 和QGraphicsItem::mapFromItem() 在项目之间映射。所有的映射功能都可以映射点,矩形,多边形和路径。

视图中提供了相同的映射功能,用于与场景之间的映射。 QGraphicsView::mapFromScene() 和QGraphicsView::mapToScene() 。要从视图映射到项目,请先映射到场景,然后再从场景映射到项目。

主要特点

缩放和旋转

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

这是一个如何在QGraphicsView的子类中实现缩放和旋转插槽的示例:

插槽可以在启用了autoRepeat的情况下连接到QToolButtons。

变换视图时,QGraphicsView可使视图的中心对齐。

有关显示如何实现基本缩放功能的代码,另请参见“Elastic Nodes Example ”。

打印

Graphics View通过其渲染功能QGraphicsScene::render() 和QGraphicsView::render() 提供单行打印。 这些函数提供相同的API:通过将QPainter传递给任一渲染函数,可以使场景或视图将其全部或部分内容渲染到任何绘画设备中。 本示例说明如何使用QPrinter将整个场景打印成整页。

场景和视图渲染功能之间的区别在于,一个在场景坐标中操作,另一个在视图坐标中操作。 QGraphicsScene::render() 通常是打印未变换场景的整个片段(例如,绘制几何数据或打印文本文档) 的首选。 另一方面,QGraphicsView::render() 适合拍摄屏幕截图; 它的默认行为是使用提供的painter渲染视口的确切内容。

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

拖放

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

要从项目开始拖动,请创建QDrag对象,并将指针传递到开始拖动的小部件。 可以同时通过多个视图观察项目,但是只有一个视图可以开始拖动。 在大多数情况下,拖动是由于按下或移动鼠标而开始的,因此在mousePressEvent() 或mouseMoveEvent() 中,您可以从事件中获取原始的窗口小部件指针。 例如:

要拦截场景的拖放事件,请在QGraphicsItem子类中重新实现QGraphicsScene::dragEnterEvent() 以及特定场景所需的任何事件处理程序。 您可以在QGraphicsScene的每个事件处理程序的文档中的“图形视图”中阅读有关拖放的更多信息。

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

另请参见“拖放机器人”示例,以了解Graphics View对拖放操作的支持。

光标和工具提示

与QWidget一样,QGraphicsItem也支持游标(QGraphicsItem::setCursor() ) 和工具提示(QGraphicsItem::setToolTip() ) 。 当鼠标光标进入项目区域时(通过调用QGraphicsItem::contains() 进行检测) ,QGraphicsView会激活光标和工具提示。

您也可以通过调用QGraphicsView::setCursor() 直接在视图上设置默认光标。

有关实现工具提示和光标形状处理的代码,另请参见“拖放机器人”示例。

动画

Graphics View支持多个级别的动画。 您可以使用动画框架轻松地组装动画。 为此,您将需要从QGraphicsObject继承项并将QPropertyAnimation与它们关联。 QPropertyAnimation允许设置任何QObject属性的动画。

另一个选择是创建一个继承自QObject和QGraphicsItem的自定义项目。 该项目可以设置自己的计时器,并通过QObject::timerEvent() 中的增量步骤控制动画。

第三个选项(主要用于与Qt 3中的QCanvas兼容) 是通过调用QGraphicsScene::advance() 来推进场景的,QGraphicsScene::advance() 依次调用QGraphicsItem::advance() 。

OpenGL渲染

要启用OpenGL渲染,只需调用QGraphicsView::setViewport() 即可将新的QOpenGLWidget设置为QGraphicsView的视口。 如果要使用抗锯齿的OpenGL,则需要使用所需的样本计数设置QSurfaceFormat(请参阅QSurfaceFormat::setSamples() ) 。

来源:hitzsf

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年2月2日
下一篇 2021年2月2日

相关推荐