【Qt】2D绘图之图形视图框架(一) 骑猪看日落 2022-11-13 01:53 214阅读 0赞 ## 00. 目录 ## ### 文章目录 ### * * 00. 目录 * 01. 概述 * 02. 开发环境 * 03. 场景(Scene) * 04. 视图(View) * 05. 图形项 * 06. 附录 ## 01. 概述 ## 在前面讲的基本绘图中,我们可以自己绘制各种图形,并且控制它们。但是,如果需要同时绘制很多个相同或不同的图形,并且要控制它们的移动、检测它们的碰撞和叠加;或者我们想让自己绘制的图形可以拖动位置、进行缩放和旋转等操作。实现这些功能,要是还使用以前的方法,那么会十分困难。解决这些问题,可以使用Qt提供的图形视图框架。 图形视图(Graphics View)框架结构的主要特点如下: * 图形视图(Graphics View)可以对大量定制的2D图形项进行管理和相互作用。视图部件可以让所有图形项可视化,它还提供了缩放和旋转功能。 * 框架中包含了一个事件传播构架,提供了和场景中的图形项进行精确的双精度交互的能力,图形项可以处理键盘事件,鼠标的按下、移动、释放和双击事件,还可以跟踪鼠标的移动。 * 图形视图框架使用一个BSP(Binary Space Partitioning)树来快速发现图形项,也正是因为如此,它可以实时显示一个巨大的场景,甚至包含上百万个图形项。 * 图形视图框架结构中,系统可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能。 图形视图结构主要包含三部分: * 场景(Scene) :QGraphicsScene类 * 视图(View) :QGraphicsView类 * 图形项(Item):QGraphicsItem类 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70] ## 02. 开发环境 ## **Windows系统**:Windows10 **Qt版本**:Qt5.15或者Qt6 ## 03. 场景(Scene) ## 场景是图形项QGraphicsItem对象的容器,其主要完成的工作包括: (1)提供用于管理大量图形项的快速接口; (2)传播事件给每一个图形项; (3)管理图形项的状态(如选择和焦点处理); (4)提供无变换的渲染功能,主要用于打印。 下面是一些QGraphicsScene的常用函数: * 可以调用QGraphicsScene: :addItem()函数将图形项添加到场景中,然后调用任意一个图形项发现函数来检索添加的图形项。 * QGraphicsScene::items()函数和其他几个重载函数可以返回符合条件的所有图形项。这些图形项不是与指定的点、矩形、多边形或者矢量路径相交,就是包含在它们之中。 * QGraphicsScene::itemAt()函数返回指定点的最上面的图形项。所有的图形项发现函数返回的图形项都是使用递减顺序(例如第一个返回的图形项在最上面,最后返回的图形项在最下面)。 * 如果要从场景中删除一个图形项,可以使用QGraphicsScene::Removeltem()函数。 * 可以通过向QGraphicsScene::setSelectionArea()函数中传递一个任意的形状来选择场景中指定的图形项。 * 如果要获取当前选取的所有图形项的列表,可以使用QGraphicsScene:: selectedltems()函数。 * 另外可以调用QGraphicsScene:: setFocusItem()或者 QGraphicsScene:: setFocus( )函数来为一个图形项设置焦点,调用QGraphicsScene:: focusItem()函数来获取当前获得焦点的图形项。 * QGraphicsScene:: render()函数将场景中的一部分渲染到一个绘图设备上。 下面先来看一个最简单的例子。新建空的Qt项目(Empty qmake Project),项目名称为myscene。然后在这个项目中添加新的C++源文件,命名为main.cpp。添加完成后首先在myscene.pro文件中添加一行代码: > QT += widgets 然后将main.cpp的内容更改如下。 #include <QApplication> #include <QGraphicsScene> #include <QGraphicsRectItem> #include <QDebug> int main(int argc, char **argv) { QApplication app(argc, argv); //新建场景 QGraphicsScene scene; //创建矩形图形项 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100); //将图形项添加到场景中 scene.addItem(item); //输出(50, 50)点处的图形项 qDebug() << scene.itemAt(50, 50, QTransform()); return app.exec(); } 这里先创建了一个场景,然后创建了一个矩形图形项,并且将该图形项添加到了场景中。然后使用itemAt()函数来返回指定坐标处最顶层的图形项,这里返回的就是刚才添加的矩形图形项。现在可以运行程序,不过因为还没有设置视图,所以不会出现任何图形界面,这时可以在应用程序输出栏中看到输出的项目的信息如下: QGraphicsItem(0x18a8720, pos=0,0) ## 04. 视图(View) ## QGraphicsView提供了视图部件,它用来使场景中的内容可视化。可以连接多个视图到同一个场景来为相同的数据集提供多个视口。 下面是一些QGraphicsView:的常用函数: * 视图部件是一个可滚动的区域,提供了一个滚动条来浏览大的场景,可以使用setDragMode()函数以QGraphicsView::SCrollHandDrag为参数来使光标变为手掌形状,从而可以拖动场景。 * 如果设置 setDragMode()的参数为QGraphicsView::RubberBandDrag,那么可以在视图上使用 鼠标拖出橡皮筋框来选择图形项。 * 默认的QGraphicsView提供了一个QWidget作为视口部件,如果要使用OpenGL进行植染,可以调用QGraphicsView::setViewport()设置QOpenGLWidget作为视口。QGraphicsView会获取视口部件的拥有权(ownership)。 在前面的程序中先添加头文件\# include ,然后main.cpp文件中的代码: #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsRectItem> #include <QDebug> int main(int argc, char **argv) { QApplication app(argc, argv); //新建场景 QGraphicsScene scene; //创建矩形图形项 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100); //将图形项添加到场景中 scene.addItem(item); //输出(50, 50)点处的图形项 qDebug() << scene.itemAt(50, 50, QTransform()); //创建视图 QGraphicsView view(&scene); //设置场景的前景色 view.setForegroundBrush(QColor(255, 255, 0, 100)); //设置场景的背景图片 view.setBackgroundBrush(QPixmap(":/image/d.png")); view.resize(400, 300); view.show(); return app.exec(); } 这里新建了视图部件,并指定了要可视化的场景。然后为该视图设置了场景前景色和背景图片。一个场景分为3层:图形项层(ItemLayer)、前景层(ForegroundLayer)和背景层(BackgroundLayer)。场景的绘制总是从背景层开始,然后是图形项层,最后是前景层。前景层和背景层都可以使用QBrush进行填充,比如使用渐变和贴图等。这里的前景色设置为半透明的黄色,当然也可以设置为其他的填充。这里要提示一下,其实使用好前景色可以实现很多特殊的效果,比如使用半透明的黑色便可以实现夜幕降临的效果。 代码中使用了 QGraphicsView类中的函数来设置场景中的背景和前景,其实也可以使用QGraphicsScene中的同名函数来实现,不过它们的效果并不完全 一样。如果使用QGraphicsScene对象设置了场景背景或者前景,那么对所有关联了该场景的视图都有效,而QGraphicsView对象设置的场景的背景或者前景,只对它本身对应的视图有效。 运行程序,效果如下图所示。可以看到矩形图形项和背景图片都是在视图中间部分进行绘制的,这个问题会在后面的坐标系统部分详细讲解。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 1] ## 05. 图形项 ## QGraphicsItem是场景中图形项的基类。图形视图框架为典型的形状提供了标准的图形项,比如矩形(QGraphicsRectlem)、椭圆(QGraphicsEllipseltem)和文本项(QGraphicsTextltem)。不过,只有编写自定义的图形项时才能发挥QGraphicsItem的强大功能。 QGraphicsItem主要支持以下功能: * 鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件; * 键盘输入焦点和键盘事件; * 拖放事件; * 分组,使用QGraphicsItemGroup通过parent-child关系来实现; * 碰撞检测。 除此之外,图形项还可以存储自定义的数据,可以使用setData()进行数据存储,然后使用data()获取其中的数据。下面自定义图形项。 在前面的程序中添加新文件,模板选择C+ +类,类名为Myltem,基类为 QGraphicsItem,类型信息选择“无”。添加完成后,在myitem.h文件中添加两个函数的声明: #ifndef MYITEM_H #define MYITEM_H #include <QGraphicsItem> class MyItem : public QGraphicsItem { public: MyItem(); //返回要绘制图形项的矩形区域 QRectF boundingRect() const; //用来执行实际的绘图操作 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; #endif // MYITEM_H 再到myitem.cpp文件中添加头文件\# include ,然后定义添加的两个函数: #include "myitem.h" #include <QPainter> MyItem::MyItem() { } //返回要绘制图形项的矩形区域 QRectF MyItem::boundingRect() const { qreal penWidth = 1; return QRectF(0 - penWidth / 2, 0 - penWidth / 2, 20 + penWidth, 20 + penWidth); } //用来执行实际的绘图操作 void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { //声明参数没有使用 Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(Qt::red); painter->drawRect(0, 0, 20, 20); } 要实现自定义的图形项,那么首先要创建一个QGraphicsItem的子类,然后重新实现它的两个纯虚公共函数:boimdingRect()和paint(),前者用来返回要绘制图形项的矩形区域,后者用来执行实际的绘图操作。其中,boimdingRect()函数将图形项的外部边界定义为一个矩形,所有的绘图操作都必须限制在图形项的边界矩形之中。而且,QGraphicsView要使用这个矩形来剔除那些不可见的图形项,另外QGraphicsItem的碰撞检测机制也需要使用到这个边界矩形。 下面到main.cpp中添加\#include “myitem.h”,将程序改为: #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsRectItem> #include <QDebug> #include "myitem.h" int main(int argc, char **argv) { QApplication app(argc, argv); //新建场景 QGraphicsScene scene; //创建矩形图形项 //QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100); MyItem *item = new MyItem; //将图形项添加到场景中 scene.addItem(item); //输出(50, 50)点处的图形项 qDebug() << scene.itemAt(50, 50, QTransform()); //创建视图 QGraphicsView view(&scene); //设置场景的前景色 view.setForegroundBrush(QColor(255, 255, 0, 100)); //设置场景的背景图片 view.setBackgroundBrush(QPixmap(":/image/d.png")); view.resize(400, 300); view.show(); return app.exec(); } 这时运行程序,效果如下图所示。可以看到,自定义的红色小方块出现在了视图的正中间,背景图片的位置也有所变化,这些问题都会在后面的坐标系统中讲到。如果只想添加简单的图形项,那么也可以直接使用图形视图框架提供的8种标准图形项。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 2] **图形视图框架提供的标准图形项** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 3] ## 06. 附录 ## 源码下载:[【Qt】2D绘图之图形视图框架(一).rar][Qt_2D_.rar] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70]: /images/20221022/c529992128e94961a5205ebe76d104ad.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 1]: /images/20221022/d66514dcea664e51ae00abb86b992cb9.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 2]: /images/20221022/2953d69402ed4c5996651a9167232669.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RlbmdqaW4yMDEwNDA0MjA1Ng_size_16_color_FFFFFF_t_70 3]: /images/20221022/4c4c3c8026f34e559ebfc01781cb8098.png [Qt_2D_.rar]: https://download.csdn.net/download/dengjin20104042056/16084024
相关 【Qt】2D绘图之图形视图框架(一) 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 场景(Scene) 骑猪看日落/ 2022年11月13日 01:53/ 0 赞/ 215 阅读
相关 【Qt】2D绘图之双缓冲绘图 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 绘制矩形 04. 青旅半醒/ 2022年11月13日 00:48/ 0 赞/ 246 阅读
相关 【Qt】2D绘图之绘图中其它问题 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 重绘事件 04. 怼烎@/ 2022年11月12日 14:57/ 0 赞/ 218 阅读
相关 【Qt】2D绘图之绘制图片 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 简单绘制图片 04 - 日理万妓/ 2022年11月12日 10:58/ 0 赞/ 239 阅读
相关 【Qt】2D绘图之渐变填充 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 线性渐变 04. 刺骨的言语ヽ痛彻心扉/ 2022年11月12日 09:45/ 0 赞/ 257 阅读
相关 【Qt】2D绘图之绘制简单的图形 00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 绘制图形 04. 拼搏现实的明天。/ 2022年11月12日 09:40/ 0 赞/ 231 阅读
相关 Qt之图形视图框架 简述 图形视图(Graphics View)提供了一个平台,用于大量自定义2D图元的管理与交互,并提供了一个视图部件(view widget)来显示可以缩放和旋转的图元。 淩亂°似流年/ 2022年06月10日 05:08/ 0 赞/ 316 阅读
相关 QT学习之图形视图框架 文章目录 坐标系统 图形项坐标 场景坐标 视图坐标 坐标映射 事件处理与传播 QGraphicsS 绝地灬酷狼/ 2022年03月25日 10:52/ 0 赞/ 320 阅读
还没有评论,来说两句吧...