Qt中QGraphicsView架构下实时鼠标绘制图形

上一章节介绍了关于QGraphicsView的基础讲解,以及简单的类图创建,由上一章节中最后展示的动画效果来看,今年主要讲述如何在QGraphicsView架构下,实时拖动鼠标绘制图形!

今天主要以矩形为例,再来看一下展示效果吧!

功能实现

想要实现鼠标拖拽绘图的效果,离不开鼠标的三大事件:按下、移动、释放

那么具体实现实时绘制矩形框的核心流程是什么呢?

第一步:鼠标左键点击,记录初始点击位置

第二步:在窗口中移动鼠标,实时获取鼠标拖动点,根据拖动点绘制指定形状

第三步:鼠标点击右键释放鼠标,绘制最终图形

描述的实现流程很简单,那么,接下来就实际操作吧!

在进行鼠标点击绘制的时候,为了兼容多个图形的实时绘制,这里,不只是用两个QPoint成员变量记录鼠标点,而是采取了vector<QPontF>容器存储的方式。

例如:三角形图形,需要三个点才能确定图形;曲线图形,是由N多个点才能确定图形;等等。。。

所以说,这里采用了vector容器进行数据存储,任何图形的点都可以进行存储。

所有的图形枚举类型,如下表格:

今天只讲述 矩形:Drawing_Rectangular

1:记录图形第一个绘制点

只有鼠标点击后才能获取当前点击点的位置,所以,记录按下点操作应该是在鼠标的mousePressEvent中实现的。

void QCustomQGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * e)
{
	//TODO:鼠标左键,点击绘制图形;鼠标右键,点击拖动图形
	QGraphicsScene::mousePressEvent(e);

	if (e->button() & Qt::LeftButton)
	{
                //当图形处于绘制状态时
		if (m_enumShape!= Drawing_Normal)
		{
			//记录鼠标按下的点
                        m_vetPoints.push_back(e->scenePos());
		}
	}
}

代码解析:当进入到鼠标按下消息后,只有在左键按下状态时,才做绘图操作,并且当前形状枚举类型有效。

2:实时获取鼠标最新位置并绘图

鼠标想要实时绘制,那一定是在鼠标的mouseMoveEvent事件中操作的。

void QCustomQGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e)
{
	//TODO:鼠标移动时,如果存在有效图形类型,进行图形绘制
	QGraphicsScene::mouseMoveEvent(e);
	if (m_enumShape!= Drawing_Normal)
	{
                m_pTempLayer->DrawShape(m_enumShape, m_vetPt, e->scenePos());
	}

}

代码解析:当鼠标进入到mouseMoveEvent事件后,并且,当前枚举类型处于有效状态时,需要实时绘制图形。

函数DrawShape的讲解

参数1:图形的枚举类型,根据不同枚举,绘制不同的图形

参数2:vector<QPointF>传入已经记录的鼠标点,可以是多个,但最少是1个。就例如当前绘制矩形来说,该容器中只是存储了一个绘制点。

参数3:鼠标在mouseMoveEvent中实时拖动点

DrawShape函数实现代码,如下:

void QTempCanvasLayer::DrawShape(ENUM_DrawingGraphic enumShape, std::vector<QPointF> vetPt, QPointF ptCurrent)
{
	m_pTempCanvasImg->fill(Qt::transparent);
	m_pTempPainter->setRenderHint(QPainter::Antialiasing, true);
	m_pTempPainter->setCompositionMode(QPainter::CompositionMode_Source);
	m_pTempPainter->setPen(QPen(QColor(51, 51, 51), 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
	switch (enumShape)
	{
	case Drawing_Circular: //圆形
		break;
	case Drawing_StraightLine: //直线
		break;
	case Drawing_Rectangular: //矩形
		m_pTempPainter->drawRect(QRectF(vetPt[0], ptCurrent));
		break;
	case Drawing_Triangle: //三角形
		break;
	case Drawing_ManyLineSegements: //多线段
		break;
	case Drawing_Curve: //曲线
		break;
	default:
		break;
	}
	update();
}

代码讲解:switch语句之前的内容都是在设置图形的风格,比如:setRenderHint防止图形走样;最需要我们注意的是下面一句代码:

m_pTempCanvasImg->fill(Qt::transparent);

如果你忘记设置了,当鼠标在拖动绘制图形时,会导致拖拽线条重叠的效果,就如下面展示效果一样,如图所示:

3:释放绘制点,绘制最终图形

鼠标事件:mouseReleaseEvent

void QCustomQGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * e)
{
	//TODO:鼠标释放之后操作
	QGraphicsScene::mouseReleaseEvent(e);

	if (m_enumShape == Drawing_Normal)
	{
		return;
	}
	//存在有效的图形类型,进行最终图形绘制
	if (e->button() & Qt::RightButton)
	{
		if (m_enumShape == Drawing_Rectangular)
		{
			//绘制直线,需要存储两个有效点
			if (m_vetPt.size() == 2)
			{
				this->DrawRealShape(m_vetPt);
                                //如果当前正在绘制图形,直接清除
				this->ClearCurrentDrawingShape(); 
			}
		}
	}
}

代码解析:触发了鼠标释放事件后,并且是鼠标右键点击(在这里都是以鼠标右键点击作为最终的图形绘制完成),此时,根据不同的枚举类型进行图形绘制。

对于矩形图形来说,只需要两个有效的点就会完整对图形的绘制,其中`this->DrawRealShape`中进行最终点的绘制。

一个图形数据绘制成功之后,需要将上一次存储的临时点进行清除,以备后续图形绘制使用,说白了,也就是vector<QPointF>容器需要清除

实现完成了鼠标的三大事件,一个完整的实时鼠标图形绘制思路已经完成了。

总结

实现鼠标实时绘图的功能,无论是MFC框架还是Qt框架,基本原理都是一致的,基本上不会离开鼠标的三大事件。

我是糯诺诺米团,一名C++开发程序媛~

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

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

相关文章

请查收“链上天眼”2023年成绩单

1月10日是中国人民警察节&#xff0c;是一份责任&#xff0c;更一份安心&#xff0c;随着科技的发展&#xff0c;链上安全领域的技术与工具不断更新迭代&#xff0c;更加安全的Web3世界正在构建。 根据欧科云链安全团队统计&#xff0c;2023 年全球范围内利用虚拟货币进行诈骗…

P1042 [NOIP2003 普及组] 乒乓球————C++

目录 [NOIP2003 普及组] 乒乓球题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 解题思路Code运行结果 [NOIP2003 普及组] 乒乓球 题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革&#xff0c;以推动乒乓球运动在全球的普及。其中 …

github上的python图片转excel,pytesseract安装相关问题

问题1&#xff1a;明明都pip install pytesseract&#xff0c;但是就是安装不上 pytesseract 未安装链接: https://pan.baidu.com/s/1I4HzCgO4mITWTcZFkdil6g?pwdafes 提取码: afes 安装后一路next&#xff0c;然后配置环境变量 C:\Program Files\Tesseract-OCR新建一个系统…

修改vscode内置Vue VSCode Snippets(代码片段)

打开插件文件夹 文件夹名是 "作者名.vscode-插件名-版本号"组成的. C:\Users\Administrator\.vscode\extensions\sdras.vue-vscode-snippets-3.1.1\snippets 打开vue.json "prefix": "vbase" 就是代码块的关键词,输入vbase就会提示代码块 …

9个自媒体音频创作平台(附链接通道)

​划到最后“阅读原文” ——进入官网 Hi&#xff0c;我是胡猛夫&#xff0c;每天分享实用运营工具&#xff01; 更多资源&#xff0c;更多内容&#xff0c;欢迎交流&#xff01;公 号 | 微视角文化 》》精彩推荐 >>微视角文化知识库&#xff1a;移动的自媒体运营百科全…

【Linux】宝塔端口不通

1.问题描述&#xff1a;端口不通 以端口16588为例&#xff1a; 服务器16588端口是关闭的&#xff0c;防火墙规则是放通的&#xff0c;是由于服务器内的对应程序没有监听到 对应 的公网上 图1&#xff1a;端口检测 图2&#xff1a; 端口已放行 此时访问仍然不通&#xff0c;但…

windows搭建银河麒麟v10虚拟机

需要用到&#xff1a; 已将安装包放置云盘 自取 VMware Workstation Pro16 https://cloud.189.cn/t/vYZNjqbQ7zUr (访问码:a2pd) 银河麒麟v10镜像 https://cloud.189.cn/t/j6ZNfmnYfYRr (访问码:1icf) 也可以去官网下载&#xff1a;https://www.kylinos.cn 1.安装VM 无…

Jenkins使用随笔

1、如果要部署的springboot程序和jenkins在同一台linux上&#xff0c;需要增加一条 export BUILD_IDtomcat_mobile_build_id 如下图&#xff1a; 原因是&#xff1a;jenkins在执行sh脚本的时候&#xff0c;如果脚本中有启动后台进程的情况&#xff0c;例如tomcat的关闭和启动…

Oracle DBCA工具图形化方式检测不到ASM磁盘组(解决各种报错)

本例环境&#xff1a; 操作系统OEL 6.5数据库版本:11.2.0.4 问题&#xff1a;DBCA建库的时候&#xff0c;检测不到ASM磁盘组 因素一&#xff1a; 可能是在授权的时候执行了 chown –R 775 /u01/app等修改权限。 分析&#xff1a;数据库无法连接ASM&#xff0c;这应该是权限…

电子学会C/C++编程等级考试2020年12月(三级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:完美立方 形如 a^3= b^3 + c^3 + d^3的等式被称为完美立方等式。例如 12^3= 6^3 + 8^3 + 10^3 。 编写一个程序,对任给的正整数 N (N≤100),寻找所有的四元组 (a, b, c, d),使得 a^3= b^3 + c^3 + d^3 ,其中 a,b,c,d均大于 11, …

Chrome DevTools 常用面板攻略

文章目录 前言一、概述1.1 简介1.2 DevTools 初步了解 二、设备模式&#xff08;Device Mode&#xff09;2.1 面板概述2.2 设备切换 三、元素面板&#xff08;Elements&#xff09;3.1 面板概述3.2 编辑样式3.2.1 添加、启用和停用 CSS 类3.2.2 添加或移除动态样式3.2.3 快速向…

UE5 通过接口实现角色描边效果

接口不能够被实例化&#xff0c;不能够在内部书写函数的逻辑和设置属性&#xff0c;只能够被继承使用。它能够让不同的类实现有相同的函数&#xff0c;继承接口的类必须实现接口的函数。 并且&#xff0c;我们可以在不同的类里面的函数实现也不同&#xff0c;比如A类描边是红色…

洗护工厂上门取送小程序具备哪些优势

上门洗衣洗鞋小程序&#xff0c;让洗衣洗鞋更简单&#xff01; 在繁忙的生活中&#xff0c;我们常常因为时间紧张而无法清洗鞋子或衣物。这时&#xff0c;一个方便快捷的上门洗衣洗鞋小程序就能够派上大用场。 这种小程序利用现代科技&#xff0c;将洗衣洗鞋服务与移动互联网相…

C# 接口(Interface)和抽象类(Abstract Class)区别和详细使用案例

文章目录 区别&#xff1a;1. **定义**&#xff1a;2. **继承与实现**&#xff1a;3. **成员**&#xff1a;4. **目的**&#xff1a; 使用示例&#xff1a;- **接口使用场景**&#xff1a;- **抽象类使用场景**&#xff1a; 在C#中&#xff0c;接口&#xff08;Interface&#…

php通用后台开发框架源码

php通用后台开发框架源码 基于ThinkPHPBootstrap的快速后台开发框架。 基于Auth验证的权限管理系统&#xff0c;支持无限级父子级权限继承&#xff0c;父级的管理员可任意 增删改子级管理员及权限设置&#xff0c;支持单管理员多角色&#xff0c;支持管理子级数据或个人数据。 …

EL表达式(上)

EL表达式 1. EL表达式是干什么的&#xff1f; - Expression Language&#xff08;表达式语言&#xff09; - EL表达式可以代替JSP中的java代码&#xff0c;让JSP文件中的程序看起来更加整洁美观 - JSP中夹杂着各种java代码&#xff0c;例如<% java代码%>等&#xff0c;导…

c#让三个线程按照顺序执行

现实的例子 三个线程都是while&#xff08;true&#xff09;的循环体 A线程&#xff1a;采集数据 B线程&#xff1a;画曲线 C线程&#xff1a;存数据库 AutoResetEvent类 AutoResetEvent 是一个线程同步的类&#xff0c;它提供了一种机制&#xff0c;允许一个或多个线程等待直…

Android 12.0 通知--PendingIntent源码分析

结论: PendingIntent 是延迟触发的一种 Intent , 通过上图的过程看,PendingIntent 的执行,是一种跨进程通信.首先创建PendingIntent对象时,就把该对象定义到 ActivityManagerService, 到执行 PengdingIntent 动作时, 也是在 ActivityManagerService 找到 目标PengdingIntent, 从…

科研绘图(三)百分比堆叠线条图

百分比堆叠线条图是一种数据可视化工具&#xff0c;它结合了堆叠面积图和线条图的特点。在这种图表中&#xff0c;时间序列数据被分成几个部分&#xff0c;每个部分代表一个类别&#xff0c;所有类别的值加起来总和为100%。这种图的每个点的堆叠区域代表不同类别在特定时间点的…

TypeScript学习笔记、鸿蒙开发学习笔记

变量定义方式 # 变量声明 let msg: string douzi console.log(msg) let num: number 20 console.log(num) let end: boolean true console.log("end" end) let a: any 10 a douzi console.log(a) let p {name:"douzi",age:20} console.log(p.name)…