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

这个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,转载注明出处🙉
📢代码改变世界,你来改变代码!✨

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【VS Code插件开发】创建终端(八)

🐱 个人主页:不叫猫先生,公众号:前端舵手 🙋‍♂️ 作者简介:前端领域优质作者、阿里云专家博主,共同学习共同进步,一起加油呀! ✨优质专栏:VS Code插件开发极速入门 📢 资料领取:前端进阶资料可以找我免费领取 目录 一、createTerminal创建终端二、终端方法1、…

PowerBI 一些基础功能(2)

1、表时间创建&#xff1a; 日期表2 ADDCOLUMNS( CALENDAR(date(2019,1,1),date(2019,12,31)), "年", YEAR ( [Date] ), "季度", ROUNDUP(MONTH([Date])/3,0), "月", MONTH([Date]), "周", weeknum([Date]), "年季度"…

uni-app微信小程序如何开发蓝牙功能

一. 前言。 蓝牙功能在我们日常软件中的使用率还是蛮高的----譬如各类共享单车/电单车。正因此&#xff0c;我们开发中接触蓝牙功能也是日渐增长。对于很多从未开发过蓝牙功能的童鞋来说&#xff0c;当PM小姐姐扔过来一个蓝牙协议要你接入时&#xff0c;简直一头雾水&#xff…

如何修改文件的修改时间?

如何修改文件的修改时间&#xff1f;随着当代社会科技的不断进步&#xff0c;我们对信息和数据的依赖程度与日俱增。在这个信息化时代&#xff0c;文件处理已经成为数字化办公中不可或缺的一部分。文件处理的范围非常广&#xff0c;其中有一个比较冷门的操作技巧&#xff0c;那…

C语言从入门到精通之【char类型】

char类型用于储存字符&#xff08;如&#xff0c;字母或标点符号&#xff09;&#xff0c;但是从技术层面看&#xff0c;char是整数类型。因为char类型实际上储存的是整数而不是字符。计算机使用数字编码来处理字符&#xff0c;即用特定的整数表示特定的字符。 char类型占1个字…

Debug知识点解析!超实用教程

一、Debug简介 二、IDEA中的Debug步骤 2.1 步过调试按钮(F8) 2.2 步入调试按钮(F7) 2.3 强制步入调试按钮(Alt Shift EZ) 2.4 步出调试按钮(Shift F8) 2.5 回退断点 2.6 运行到光标处&#xff08;F9&#xff09; 2.7 计算表达式按钮(Alt F8) 三、条件断点 在断点处右…

[Kettle] 记录处理

1.排序记录 排序是对数据中的无序记录&#xff0c;按照自然或客观规律&#xff0c;根据关键字段大小递增或递减的次序&#xff0c;对记录重新排列的过程 数据源 2019年11月月考数学成绩(Kettle数据集3).xlshttps://download.csdn.net/download/Hudas/88521681 2019年11月月考…

Mysql5.7创建远程账号和新建数据库

文章目录 Mysql5.7创建远程账号和新建数据库创建远程账号新建默认数据库默认数据库指定字符集数据库写法一写法二 查看数据库列表查看数据库的定义声明 Mysql5.7创建远程账号和新建数据库 创建远程账号 CREATE USER mm% IDENTIFIED WITH mysql_native_password BY mm1122;Que…

将算力普惠到底阿里云开启金秋云创季: 数百款爆品享专属特惠价(阿里云2023年双十一)

11月9日消息&#xff0c;国内领先云计算厂商阿里云近日在官网推出了“金秋云创季”活动&#xff0c;为开发者和企业带来了多重福利&#xff0c;包括上云必备的2C2G 3M固定带宽云服务器仅需99元/年、上百款核心云产品的专属特惠价、最高5580元的满减券大礼包&#xff0c;不断降低…

绕过PPL机制窃取凭证

Mimikatz窃取凭证攻击 正常权限cmd情况下mimikatz是无法直接提权的,所以窃取密码更是不行的。 但管理员权限下的mimikatz是可以获取到主机登陆密码的。 PPL安全机制 在此之前,用户只需要使用SeDebugPrivilege令牌权限即可获取任意进程的所有访问权限;随后Windows8.1 在此…

Ant Design Vue Select下拉框内容显示不全问题解决

默认情况下&#xff0c;当下拉框的内容长度过长时&#xff0c;会被折叠&#xff0c;这比较影响用户体验&#xff0c;查了下文档&#xff0c;看到有一个属性可以解决这个问题&#xff1a; 没设置的下拉效果&#xff1a; 设置完之后&#xff1a;dropdownMatchSelectWidth{false}&…

pytest自动化测试两种执行环境切换的解决方案

一、痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&#xff0c;比如多套测试环境、预上线环境、UAT环境、线上环境等等&#xff0c;并且在DevOps理念中&#xff0c;往往自动化都会与Jenkins进行CI/CD&#xff0c;不论是定时执行策略…

Ora2Pg工具迁移Oracle到openGauss

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

2022年12月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 下面哪个语句正确定义了元组类型数据tuple1?( ) A: tuple1=[“张三”,“李四”,“王五”] B: tuple1=(“张三”;“李四”;“王五”) C: tuple1=(张三,李四,王五) D: tuple1=(“张三…

C语言从入门到精通之【printf和scanf函数】

printf()是输出函数&#xff0c;scanf()是输入函数&#xff0c;但是它们的工作原理几乎相同。两个函数都使用格式字符串和参数列表。 printf()函数的格式 printf( 格式字符串, 待打印项1, 待打印项2,…);待打印项1、待打印项2等都是要打印的项。它们可以是变量、常量&#xff…

【论文阅读】GAIN: Missing Data Imputation using Generative Adversarial Nets

论文地址&#xff1a;[1806.02920] GAIN: Missing Data Imputation using Generative Adversarial Nets (arxiv.org)

应用层——HTTPS协议

文章目录 一.HTTPS协议介绍二.关于加密1.什么是"加密"2.为什么要加密3.常见的加密方式4.数据摘要 && 数据指纹 三.HTTPS的工作过程探究1.方案1 —— 只使用对称加密&#xff08;明文传输不可取&#xff09;2.方案2 —— 只使用非对称加密&#xff08;仅单向安…

【数据分享】2015-2023年我国地级市逐月房价数据(Excel格式/Shp格式)

房价是一个城市发展程度的重要体现&#xff0c;一个城市的房价越高通常代表这个城市越发达&#xff0c;对于人口的吸引力越大&#xff01;因此&#xff0c;房价数据是我们在各项城市研究中都非常常用的数据&#xff01;之前我们分享过我国主要城市2023年房价数据&#xff08;可…

Vue基础必备掌握知识点-Vue的指令系统讲解(二)

Vue指令系统继续讲解 v-for 作用:基于数据进行循环&#xff0c;多次渲染整个元素 数据类型:数组.对象.数字。。。 遍历数组语法&#xff1a;v-for"(item,index)" in 数组 item:表示每一项 index:则是表现下标 注意:v-for中的key值&#xff0c;key属性唯一的…