Qt开发技术:图形视图框架(一)基本介绍

若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/115791408
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么本身研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)框架

Qt开发专栏:开发技术(点击传送门)

上一篇:无
下一篇:敬请期待函数


前话

  使用到Qt的视图框架。工具


Qt视图框架介绍

简介

  图形视图框架(The Graphic View Framework)用于管理和与大量定制的二维图形项目交互,以及用于可视化项目的视图小部件,支持缩放和旋转。
  在这里插入图片描述布局

  该框架包括一个事件传播体系结构,容许对场景中的项目进行精确的双精度交互。项目能够处理按键事件、鼠标按下、移动、释放和双击事件,还能够跟踪鼠标移动。
  图形视图使用BSP(Binary Space Partitioning,即二进制空间分区)树提供很是快读得项目发现,所以,它能够实时现实大型场景,即便有数百万个项目。
  图形视图提供了一种基于项目得模型视图变成方法,多个视图能够观察单个场景,而且场景包含不一样几何图形的项目。性能

场景(The Scene)

  QGraphicsScene提供了图形视图场景,场景有以下职责:字体

  • 为管理大量项目(图元项目)提供快速界面;(实测同一个区域不能重叠多了,绘制会卡顿)
  • 将事件传播到每一个项;
  • 管理项目状态,如选择和焦点处理;
  • 提供未转换的渲染功能;主要用于打印;

  该场景用做QGraphicsItem对象的容器。经过调用QGraphicsItem::additem() 将项添加到场景中,而后经过调用多个项发现函数之一来检索项。QGraphicsItem::items()及其重载返回由点、矩形、多边形或常规矢量路径包含或与之相交的全部项。QGraphicsItem::itemAt()返回特定点的最上面的项。全部项目发现功能都按降序堆叠顺序返回项目(即第一个返回的项目是最上面的,最后一个项目是最下面的)。优化

QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100))
QTransform transform;;
QGraphicsItem *item = scene.itemAt(50, 50, transform);
// item == rect

  QGraphicsScene的事件传播体系结构安排将场景事件传递到项目,并管理项目之间的传播。若是场景在某个位置接收到鼠标按下事件,则场景将事件传递到该位置的任何项目。
  QGraphicsScene还管理某些项状态,例如项选择和焦点。能够经过调用QGraphicsScene::setSelectionArea(),传递任意形状来选择场景中的项目。该功函数还可用做QGraphicsView中橡皮擦的选择区域。要获取全部当前选定项的列表,请调用QGraphicscene::selecteditems()。QGraphicsScene处理的另外一个状态是项是否具备键盘输入焦点。能够经过调用QGraphicScene::setFocusItem()或 QGraphicsItem::setFocus()对项设置焦点,也能够经过调用QGraphicscene::focusItem()获取当前焦点项。
  最后,QGraphicScene容许您经过QGraphicScene::render()函数将部分场景渲染到绘制设备中。能够“打印”部分了解更多有关此内容的信息。动画

视图(The View)

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

QGraphicsScene scene;
myPopulateScene(&scene);
QGraphicsView view(&scene);
view.show();

  在将事件发送到可视化场景以前,视图从键盘和鼠标接收输入事件,并将其转换为场景事件(在适当的状况下将使用的坐标转换为场景坐标)。
  用转换矩阵QGraphicsView::transform(),视图能够转换场景的坐标系。这容许高级导航功能,如缩放和旋转。为了方便起见,qgraphicsView还提供了在视图和场景坐标之间转换的函数:QGraphicsView::mapToScene()和 QGraphicsView::mapFromScene()。
  在这里插入图片描述.net

项目(The Item):图形元素

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

  • 鼠标按下、移动、释放和双击事件,以及鼠标悬停事件、滚轮事件和上下文菜单事件;
  • 键盘输入焦点和按键事件;
  • 拖放;
  • 分组,经过父子关系,经过QGraphicsItemGroup;
  • 碰撞检测;

  项目位于本地坐标系中,与QGraphicsView相似,它还提供许多功能,用于在项目和场景之间以及从项目到项目之间映射坐标。此外,与QGraphicsView同样,它可使用矩阵:QGraphicsItem::Transform()转换其坐标系。这对于旋转和缩放单个项目颇有用。
  项能够包含其余项(子项)。父项的转换由其全部子项继承。可是,无论一个项的累积转换如何,它的全部函数(例如,QGraphicsItem::contains()QGraphicsItem::boundingRect()QGraphicsItem::collectsWith() 仍在本地坐标中操做。
  QGraphicsItem支持经过QGraphicsItem::shape()函数和QGraphicsItem::collipswith() 进行冲突检测,这两个函数都是虚拟函数。经过从QGraphicsItem::shape() 中返回项目的形状做为本地坐标QPaineterPath,QGraphicsItem将为您处理全部冲突检测。可是,若是您但愿提供本身的碰撞检测,则能够从新实现QGraphicsItem::CollipsWith()
  在这里插入图片描述

Qt图形视图框架中的类

  这些类为建立交互式应用程序提供了一个框架。
  在这里插入图片描述


图形视图坐标系

  图形视图基于笛卡尔坐标系;场景中项目的位置和几何图形由两组数字表示:X坐标和Y坐标。使用未转换视图观察场景时,场景中的一个单元由屏幕上的一个像素表示。
  注意:因为图形视图使用qt坐标系,所以不支持倒Y轴坐标系(Y向上增加)。
  图形视图中有三个有效的坐标系:项目坐标、场景坐标和视图坐标。为了简化实现,图形视图提供了方便的功能,容许您在三个坐标系之间进行映射。
  渲染时,图形视图的场景坐标对应于QPainer的逻辑坐标,视图坐标与设备坐标相同。后续会说明逻辑坐标和设备坐标之间的关系。
  在这里插入图片描述

项目坐标

  项目在本身的本地坐标系中。它们的坐标一般以中心点(0,0)为中心,这也是全部变换的中心。项目坐标系中的几何基元一般称为项目点、项目线或项目矩形。
  在建立自定义项时,只须要担忧项坐标;QGraphicsScene和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如何肯定场景的哪些区域已更改的基础。场景中的更改经过QGraphicsScene::changed()信号进行通讯,参数是场景矩形的列表。

视图坐标

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

坐标映射

**  在处理场景中的项目时,一般能够将坐标和任意形状从场景映射到项目、从项目映射到项目或从视图映射到场景。例如,在QGraphicsView的视区中单击鼠标时,能够经过调用QGraphicsView::mapToScene(),而后调用QGraphicsScene::ItemAt()来询问场景光标下的项目。若是要知道某个项在视区中的位置,能够对该项调用QGraphicsItem::MapToScene(),而后在视图上调用QGraphicsView::MapFromSecene()。最后,若是要查找视图椭圆中的项目,能够将QPaineterPath传递给mapToScene(),而后将映射的路径传递给QGraphicScene::items()。
  经过调用QGraphicsItem::MapToScene()和QGraphicsItem::mapFromScene(),能够将坐标和形状映射到项的场景或从中映射。还能够经过调用QGraphicsItem::mapTopParent()和qgraphicsItem::mapFromParent()映射到项的父项,或者经过调用QGraphicsItem::MapToItem()和QGraphicsItem::mapFromItem()在项之间映射。全部映射函数均可以映射点、矩形、多边形和路径。
  视图中有相同的映射函数,可用于映射到场景或从场景映射到场景。QGraphicsView::mapFromSecene()和QGraphicsView::mapToScene()。要从视图映射到项目,首先映射到场景,而后从场景映射到项目。**


关键特征

缩放和旋转

  QGraphicsView支持与QPainer经过QGraphicsView::setMatrix()进行的相同的仿射转换。经过对视图应用转换,您能够轻松地添加对常见导航功能(如缩放和旋转)的支持。
如下是如何在QGraphicsView子类中实现缩放和旋转插槽的示例:

class View : public QGraphicsView
{
  Q_OBJECT
  ...
public slots:
  void zoomIn() { scale(1.2, 1.2); }
  void zoomOut() { scale(1 / 1.2, 1 / 1.2); }
  void rotateLeft() { rotate(-10); }
  void rotateRight() { rotate(10); }
  ...
};

  槽函数能够链接到启用自动重复的QToolButtons。
  转换视图时,QGraphicsView保持视图中心对齐。
  有关如何实现基本缩放功能的代码,后续会有示例描述。

项目组

  经过使一个项目成为另外一个项目的子项目,您能够实现项目分组最基本的特性:

  • 项目将一块儿移动
  • 全部转换都从父项目传播到子项目。

  此外,QGraphicsItemGroup是一个特殊的项,它将子事件处理与用于向组中添加和删除项的有用接口结合在一块儿。将项添加到QGraphicsItemGroup将保留该项的原始位置和转换,而一般从新设置项将致使子项相对于其新父项从新定位自身。为了方便起见,能够经过调用QGraphicScene::CreateItemGroup()经过场景建立QGraphicsItemGroups。

小部件和布局

Qt4.4经过QGraphicsWidget引入了对几何和布局感知项的支持。这个特殊的基项相似于QWidget,但与QWidget不一样,它不是从QPaintDevice继承的,而是从QGraphicsItem继承的。这容许您编写带有事件、信号和槽、大小提示和策略的完整小部件,还能够经过QGraphicsLinearLayout和QGraphicsGridLayout在布局中管理小部件的几何图形。

QGraphicsWidget

  基于QGraphicsItem的功能和精简的占地面积,QGraphicsWidget提供了两个方面的最佳功能:QWidget的额外功能,例如样式、字体、调色板、布局方向及其几何图形,以及QGraphicsItem的分辨率独立性和转换支持。由于图形视图使用实坐标而不是整数,因此QGraphicsWidget的几何函数也在QRectF和QPointF上运行。这也适用于框架矩形、边距和间距。例如,对于QGraphicsWidget,指定内容页边距(0.五、0.五、0.五、0.5)并很多见。您能够建立子窗口和“顶级”窗口;在某些状况下,您如今能够为高级MDI应用程序使用图形视图。
  一些QWidget的属性是受支持的,包括窗口标志和属性,但不是所有。参考QGraphicsWidget的类文档,以全面了解什么是受支持的,什么是不受支持的。例如,能够经过将Qt::window标志传递给QGraphicsWidget的构造函数来建立装饰窗口,但图形视图当前不支持MacOs上常见的Qt::Sheet和Qt:: Drawer标志。

QGraphicsLayout

  QGraphicsLayout是专门为QGraphicsWidget设计的第二代布局框架的一部分。它的API与QLayout很是类似。您能够在QGraphicsLinearLayout和QGraphicsGridLayout中管理小部件和子布局。您还能够经过本身对QGraphicsLayout子类化来轻松地编写本身的布局,或者经过编写QGraphicsLayoutItem的适配器子类,将本身的QGraphicsItem项添加到布局中。

嵌入式小部件支持

  图形视图为在场景中嵌入任何小部件提供无缝支持。您能够嵌入简单的小部件,如QLineEdit或QPushButton,复杂的小部件,如QTabWidget,甚至完整的主窗口。要将小部件嵌入到场景中,只需调用QGraphicScene::AddWidget(),或建立QGraphicsProxyWidget实例手动嵌入小部件。
  经过QGraphicsProxyWidget,图形视图可以深刻集成客户端小部件的功能,包括其光标、工具提示、鼠标、平板电脑和键盘事件、子小部件、动画、弹出窗口(如QComboBox或QCompeter),以及小部件的输入焦点和激活。QGraphicsProxyWidget甚至集成了嵌入式小部件的选项卡顺序,这样您就能够在嵌入式小部件中插入和取出选项卡。甚至能够将新的QGraphicsView嵌入到场景中,以提供复杂的嵌套场景。
  当转换嵌入的小部件时,图形视图确保小部件独立地转换分辨率,容许字体和样式在放大时保持清晰。(请注意,分辨率独立性的效果取决于样式。)


性能

浮点指令

  为了准确、快速地对项目应用转换和效果,在假设用户的硬件可以为浮点指令提供合理性能的前提下,构建了图形视图。
  许多工做站和台式计算机都配备了适当的硬件来加速这种计算,可是一些嵌入式设备可能只提供库来处理数学运算或模拟软件中的浮点指令。
  所以,某些类型的影响在某些设备上可能比预期的慢。能够经过在其余区域进行优化来补偿这种性能损失;例如,使用OpenGL渲染场景。可是,若是这些优化还依赖于浮点硬件的存在,那么它们自己可能会致使性能下降。


上一篇:无
下一篇:敬请期待


若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/115791408

相关文章
相关标签/搜索