《QT从基础到进阶·二十六》绘制多个图形项(QGraphicsRectItem,QGraphicsLineItem,QGraphicsPolygonItem)

news2024/11/27 12:36:46

这个demo用QT实现了对多个图形项的绘制,包括矩形的绘制,直线的绘制和多边形的绘制,是之前一章中绘制矩形的增强版,之前一章节关于矩形的绘制可以参考:《QT从基础到进阶·十五》用鼠标绘制矩形(QGraphicsView、QPainter、QGraphicsRectItem)

对比于之前一章关于矩形的绘制,在这一章节中对多个图形项的绘制用了一种新的实现方式:
1、创建了DrawControl类管理所有绘制的图形项,同时DrawControl被外部调用;
2、创建drawRect继承QGraphicsRectItem,用于绘制矩形;
3、创建drawLine继承QGraphicsLineItem,用于绘制直线;
4、创建drawPolygon继承QGraphicsPolygonItem,用于绘制多边形;
后续可以继续追加其他图形项的绘制,所有图形项都被DrawControl管理。

源码放在最后面

DrawControl目前包含一个头文件(DrawPolygons.h)和一个CPP文件(DrawPolygons.cpp),头文件对外暴露的接口如下:

class DrawControl : public QObject
{
	Q_OBJECT
public:
	DrawControl(QGraphicsView* view, QGraphicsScene* sence, QObject* parent = nullptr);
	~DrawControl();

public:
	//创建绘画类型:矩形,圆...
	//isPaintingEnable设置false表示通过参数绘制多边形,同时禁用paint绘画功能
	QGraphicsItem* createDrawObject(polygons drawType, color color,int penWidth = 1, bool isPaintingEnable = false);

	//根据矩形参数绘制矩形
	void draw_Rect(QRect rect, QGraphicsItem* itemPtr);

	//根据直线参数绘制直线
	void draw_Line(QLine line, QGraphicsItem* itemPtr);

	//根据多边形参数绘制多边形
	void draw_Polygon(QPolygon polygon, QGraphicsItem* itemPtr);
	
public:
	//获取所有创建的图形项item对象指针
	std::map<polygons, std::map<int, QGraphicsItem*>> getAllGraphicsItems();

	//鼠标按下开始绘画,需接收QGraphicsView中的mousePressEvent事件坐标(视图view坐标)
	void mouseDrawBegin(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr, Qt::MouseButton button = Qt::MouseButton::LeftButton);

	//鼠标已经按下,移动鼠标进行绘画或者移动多边形,需接收QGraphicsView中的mouseMoveEvent事件坐标(视图view坐标)
	void mouseDrawProgress(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr);

	//鼠标松开,完成绘画或完成拖动,需接收QGraphicsView中的mouseReleaseEvent事件坐标(视图view坐标)
	void mouseDrawEnd(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr, Qt::MouseButton button = Qt::MouseButton::LeftButton);

	//实时更新鼠标形状,需接收QGraphicsView中的mouseMoveEvent事件坐标(视图view坐标)
	void updateMouseShape(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr);
}

目前绘制图形项有两种方式:
(1)通过对DrawControl传参自动绘制图形项
(2)通过DrawControl的鼠标事件手动用鼠标绘制图形项

下面分别说下两种方式的使用:
(1)通过对DrawControl传参自动绘制图形项
第一步:我们需要在自定义GraphicsView类中包含DrawPolygons.h头文件,并声明DrawControl指针,同时在声明要绘制的图形项的指针。

 DrawControl* drawControl;  //声明所有图形项管理器指针
 QGraphicsItem* rect_item;  //声明矩形指针
 QGraphicsItem* line_item;  //声明直线指针
 QGraphicsItem* polygons_item;  //声明多边形指针

第二步:在自定义GraphicsView类中创建DrawControl对象,并通过DrawControl管理器分别创建要绘制的图形项对象。

//创建DrawControl对象需要传入QGraphicsView和QGraphicsScene指针
drawControl = new DrawControl(this, m_scene);
rect_item = drawControl->createDrawObject(polygons::rect, color::blue);  //创建矩形对象
polygons_item = drawControl->createDrawObject(polygons::polygon, color::red); //创建多边形对象
line_item = drawControl->createDrawObject(polygons::line, color::red);  //创建直线对象

createDrawObject接口分析:

QGraphicsItem* createDrawObject(polygons drawType, color color,int penWidth = 1, bool isPaintingEnable = false);

参数1:要创建哪个图形项对象,为enum类型;

typedef enum Polygons
{
	rect,  //矩形
	line,  //直线
	polygon, //多边形
	none
}polygons;

参数2:绘制的线条颜色,enum类型;

typedef enum Color
{
	red,
	blue,
	black
}color;

参数3:绘制图形项时线条的宽度,默认为1;
参数4:是否禁用paint绘制事件,默认为false,表示方式1,通过给参数自动创建图形项,设置true表示方式2,可以用鼠标手动绘制图形项。

第三步:设置参数自动绘制矩形,直线和多边形

void GraphicsView::drawPolygon_()
{
    //绘制矩形
    drawControl->draw_Rect(QRect(0, 0, 100, 100), rect_item);
    
    //绘制多边形
    QPolygon polygon;
    polygon << QPoint(200, 100) << QPoint(250, 150) << QPoint(150, 150) << QPoint(150, 100);
    drawControl->draw_Polygon(polygon, polygons_item);

    //绘制直线
    drawControl->draw_Line(QLine(80,80,180,80), line_item);
    
}

矩形左上角坐标为(0, 0)点,宽高为100。多边形分别设置点(200, 100),(250, 150),(150, 150), (150, 100),坐标相连实际绘制一个梯形。直线两点坐标分别为(80, 80), (180, 80),是一条水平线。示意图如下:
在这里插入图片描述

(2)通过DrawControl的鼠标事件手动用鼠标绘制图形项

1、用鼠标手动绘制矩形

在GraphicsView构造中创建DrawControl绘制管理器对象和矩形对象。

//创建绘制管理器对象
 drawControl = new DrawControl(this, m_scene);
 //创建矩形对象,绘制线条设置蓝色,线条宽度设置1, true开启paint绘制事件
 rect_item = drawControl->createDrawObject(polygons::rect, color::blue, 1, true);

在GraphicsView鼠标事件中调用drawControl 中的鼠标事件,主要有三个鼠标事件:鼠标按下,鼠标移动,鼠标放开。
drawControl的鼠标事件接口分析:

//鼠标按下开始绘画,需接收QGraphicsView中的mousePressEvent事件坐标(视图view坐标)
void mouseDrawBegin(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr, Qt::MouseButton button = Qt::MouseButton::LeftButton);

参数1:上文说到的绘制类,enum类型;
参数2:传入的鼠标点击的坐标;
参数3:绘制的图形项指针;
参数4:传入鼠标左键按下还是右键按下,默认左键按下

//鼠标已经按下,移动鼠标进行绘画或者移动多边形,需接收QGraphicsView中的mouseMoveEvent事件坐标(视图view坐标)
void mouseDrawProgress(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr);

参数1:上文说到的绘制类,enum类型;
参数2:传入鼠标移动时的坐标;
参数3:绘制的图形项指针;

//鼠标松开,完成绘画或完成拖动,需接收QGraphicsView中的mouseReleaseEvent事件坐标(视图view坐标)
void mouseDrawEnd(polygons drawType, const QPoint& point, QGraphicsItem* itemPtr, Qt::MouseButton button = Qt::MouseButton::LeftButton);

参数1:上文说到的绘制类,enum类型;
参数2:传入鼠标松开的坐标;
参数3:绘制的图形项指针;
参数4:传入鼠标左键松开还是右键松开,默认左键松开

GraphicsView中的调用:

//鼠标按下
void GraphicsView::mousePressEvent(QMouseEvent* event)
{
	drawControl->mouseDrawBegin(polygons::rect, event->pos(), rect_item);
	QGraphicsView::mousePressEvent(event);
}

//鼠标移动
void GraphicsView::mouseMoveEvent(QMouseEvent* event)
{
   drawControl->mouseDrawProgress(polygons::rect, event->pos(), rect_item);
   //updateMouseShape能够更新鼠标移动时鼠标箭头图标变化,比如鼠标移入矩形内会从箭头变为手,目前只实现了矩形鼠标图标变化
   drawControl->updateMouseShape(polygons::rect, event->pos(), rect_item);
   QGraphicsView::mouseMoveEvent(event);
}

//鼠标放开
void GraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
    drawControl->mouseDrawEnd(polygons::rect, event->pos(), rect_item);
    QGraphicsView::mouseReleaseEvent(event);
}

效果示意图如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/61b69688381a4e579df37ec46946f43d.gif

2、用鼠标绘制直线

//GraphicsView.cpp
 drawControl = new DrawControl(this, m_scene);
 line_item = drawControl->createDrawObject(polygons::line, color::red, 1, true);

GraphicsView中的调用:

//鼠标按下
void GraphicsView::mousePressEvent(QMouseEvent* event)
{
	drawControl->mouseDrawBegin(polygons::line, event->pos(), line_item);
	QGraphicsView::mousePressEvent(event);
}

//鼠标移动
void GraphicsView::mouseMoveEvent(QMouseEvent* event)
{
   drawControl->mouseDrawProgress(polygons::line, event->pos(), line_item);
   QGraphicsView::mouseMoveEvent(event);
}

//鼠标放开
void GraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
    drawControl->mouseDrawEnd(polygons::line, event->pos(), line_item);
    QGraphicsView::mouseReleaseEvent(event);
}

效果示意图如下:
在这里插入图片描述

3、用鼠标绘制多边形

//GraphicsView.cpp
 drawControl = new DrawControl(this, m_scene);
 polygons_item = drawControl->createDrawObject(polygons::polygon, color::red, 1, true);

GraphicsView中的调用:

//鼠标按下
void GraphicsView::mousePressEvent(QMouseEvent* event)
{
	//绘制多边形涉及鼠标左右键点击,所有需要最后一个参数需要传入鼠标类型
	drawControl->mouseDrawBegin(polygons::line, event->pos(), line_item, event->button());
	QGraphicsView::mousePressEvent(event);
}

//鼠标移动
void GraphicsView::mouseMoveEvent(QMouseEvent* event)
{
   drawControl->mouseDrawProgress(polygons::polygon, event->pos(), polygons_item);
   QGraphicsView::mouseMoveEvent(event);
}

//鼠标放开
void GraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
    drawControl->mouseDrawEnd(polygons::polygon, event->pos(), polygons_item,  event->button());
    QGraphicsView::mouseReleaseEvent(event);
}

注意:多边形的绘制是先点击鼠标左键不松开,再点击右键,松开右键后确定第一个点,这时鼠标左键依旧不松开,移到其他地方再点击右键,松开右键确定第二个点,以此往复,当松开鼠标左键后会自动把这些点连成线形成一个多边形。

效果示意图如下:
在这里插入图片描述

源码下载

📢博客主页: 主页
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 梦回阑珊 原创,首发于 CSDN,转载注明出处🙉
📢代码改变世界,你来改变代码!✨

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1207707.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

远程登录Linux方法(Linux平台相互远程;Windows远程登录Linux、远程编码、文件传输;无法远程登录的问题解决;c程序的编译)

在实际使用Linux系统过程中我们不可避免的需要远程登录Linux&#xff0c;这是因为未来大家使用Linux服务器的时候你所对应的那台Linux服务器不一定提供界面(服务器可能在外地)。本篇将会介绍远程登录Linux的方法。 文章目录 1. SSH介绍2. Linux平台相互远程及文件传输2.1 Linux…

准备搞OpenStack了,先装一台最新的Ubuntu 23.10

正文共&#xff1a;1113 字 25 图&#xff0c;预估阅读时间&#xff1a;2 分钟 依稀记得前面发了一篇Ubuntu的安装文档&#xff08;66%的经验丰富开发者和69%的学生更喜欢的Ubuntu的安装初体验&#xff09;&#xff0c;当时安装的是20.04.3的版本&#xff0c;现在看来已经是非常…

C语言数据结构-----栈和队列(概念,代码实现及简单练习)

前言 本篇主要介绍栈和队列的相关知识&#xff0c;练习以及代码实现。 代码主要展示部分功能的实现。完整代码在gitee上查看。 链接: 栈和队列的完整代码实现 文章目录 前言1.栈1.1 栈的概念及结构1.2 栈的实现1.3 栈的代码实现1.3.1 栈的初始化1.3.2 栈顶插入1.3.3 栈顶删除1…

若依框架修改包名报错

1.首先看下报错截图 启动GateWay 2.这个是因为 我改了里面的包名就是下面 ruoyi改成screen爆了上面的问题 3.那么关键的来了&#xff0c;我测了下 改了core不管启动gateway还是modules里面任何一个都会爆打不开工具类的问题 &#xff0c;我看了其他pom也没有引用core&#xff…

功能强大的国产API管理神器 Eolink,亲测好用

前言 大家好&#xff0c;我是小月&#xff0c;今天给大家讲讲最近很火的Eolink&#xff0c;一款功能强大且非常实用的国产 API管理工具。在我们日常的前端、后端开发测试过程中经常会用到API&#xff0c;特别是在大型项目中API管理工具也就必不可少。工欲善其事必先利其器&…

[模版总结] - 树的基本算法1 - 遍历

树结构定义 一种非线性存储结构&#xff0c;具有存储“一对多”关系的数据元素集合 种类 General Tree TrieB/B 树二叉树 满/完满/完全二叉树 完美BT : 除了叶子结点外所有节点都有两个字节点&#xff0c;每一层都完满填充完全BT&#xff1a; 除最后一层以外其他每一层都完美…

FaceBook登录提示密码错误的原因及解决方法

下面这一种类型的提示密码错误&#xff0c;大家首先能够想到的可能就是本身的账号密码有错误&#xff0c;但这个只代表其一。有一种情况的话&#xff0c;他可能根本不是账号或者密码的错误&#xff0c;他仅仅是因为注册的地方和登录的地方不太一样&#xff0c;也会造成这样的结…

【JavaEE初阶】IP协议简介

文章目录 前言&#x1f334;IP协议的概念&#x1f333;IP数据报&#x1f6a9;IPv4协议头格式&#x1f6a9;IPv6的诞生 &#x1f38d;IP地址&#x1f6a9;IP地址的格式&#xff1a;&#x1f6a9;IP地址的分类&#x1f388;网络号与主机号的划分 &#x1f6a9;特殊的IP地址&#…

QGIS之十九矢量投影

效果 步骤 1、准备数据 2、Qgis矢量投影 Qgis工具箱中搜索“投影” 3、结果

算法笔记-第七章-栈的应用(未完成)

算法笔记-第七章-栈的应用 栈的基本常识栈的解释一栈的解释二 栈的操作序列合法的出栈序列可能的出栈序列补充知识点 后缀表达式&#xff08;无优先级&#xff09; 栈的基本常识 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表。 栈的解释一 栈的…

Vue dev-tools的安装

安装 Vue 开发者工具&#xff0c;装插件调试Vue应用 1.通过谷歌应用商店来进行安装&#xff08;国外网站&#xff09; 2.极简插件&#xff1a; 搜索 Vue -> 下载解压 -> 浏览器扩展模式打开&#xff0c;开发者模式 -> 将解压的CRX文件拖拽安装 -> 插件详情 &…

YOLOV8目标识别——详细记录从环境配置、自定义数据、模型训练到模型推理部署

一、概述 Yolov8建立在Yolo系列历史版本的基础上&#xff0c;并引入了新的功能和改进点&#xff0c;以进一步提升性能和灵活性。Yolov8具有以下特点&#xff1a; 高效性&#xff1a;Yolov8采用了新的骨干网络、新的Ancher-Free检测头和新的损失函数&#xff0c;可在CPU到GPU的…

在SpringBoot中使用EhCache缓存

在使用EhCache缓存之前&#xff0c;我们需要了解的是EhCache缓存是啥&#xff1f; Ehcache的概述 Ehcache是一个开源的Java缓存框架&#xff0c;用于提供高效的内存缓存解决方案&#xff0c;他可以用于缓存各种类型的数据&#xff0c;包括对象&#xff0c;查询结果&#xff0…

软件测试行业趋势分析

1 绪论 本文先对互联网对时代和社会变革进行了论述&#xff0c;然后再由互联网时代对软件工业模式变革进行了介绍&#xff0c;最后引出附属于软件工业的测试行业在新形势下的需求变化&#xff0c;并对趋势进行了分析&#xff0c;并最终给出了相关的从业人员的职业发展建议。 …

3DMAX建模基础教程:实例与复制

3D Studio Max&#xff0c;或称3DMAX&#xff0c;是一种专业的三维计算机图形软件&#xff0c;被广泛应用于电影、电视、游戏开发等领域。以下是一份关于3DMAX建模基础教程的实例与复制的详解。 3D模型实例化 实例化是一种重复使用相同对象的技术&#xff0c;而无需每次都创建…

搭建网站选择弹性云服务器

​ 弹性云服务器已成为建站的首选方案&#xff0c;弹性云服务器并从成本、灵活性、可扩展性和安全性等多个角度进行分析。 一、成本控制弹性云服务器以其优势的弹性计费模式&#xff0c;在建站初期成本控制中占据了重要地位。与传统的物理服务器相比&#xff0c;弹性云服务器可…

深度对话:以实在RPA Agent智能体安全机制破解LLM应用谜题

AI大模型席卷全球&#xff0c;为各个行业带来了颠覆式创新机遇&#xff0c;同时也打开了未知的潘多拉魔盒。随着大语言模型能力的不断增强和适用范围延伸&#xff0c;大模型本身带来的隐私泄漏、数据安全等问题越发成为各大厂商关注的核心&#xff0c;引发了各界更多的思考与发…

软件测试 —— 常见的自动化测试架构!

一个自动化测试架构就是一个集成体系&#xff0c;其中定义了一个特殊软件产品的自动化测试规则。这一体系中包含测试功能函数库、测试数据源、测试对象识别标准&#xff0c;以及各种可重用的模块。这些组件作为小的构建模块&#xff0c;被组合起来代表某种商业流程。自动化测试…

组件库篇 | EUI | 快速上手

组件库篇 | EUI | 快速上手 导入组件库 仅需三个步骤便可以导入组件库&#xff1a; 进入main.cpp所在目录&#xff0c;将EUI文件夹复制到该目录下 双击sln文件使用vs打开项目&#xff0c;右键项目名-添加-新建筛选器&#xff0c;命名为EUI 将第1步导入的EUI文件夹拖入到第2步…

做C语言的编程题总是想骂人怎么办?

做C语言的编程题总是想骂人怎么办&#xff1f; 可能C语言的编程题难住了您吧&#xff0c;导致情绪激烈不平静&#xff0c;那么做C语言的编程题可以顺利-些吗? 当然有一些方法可是现实此目标的:最近很多小伙伴找我&#xff0c;说想要一些C语言的资料&#xff0c;然后我根据自己…