Qt(十二)Graphics View 绘图架构(三)

文章目录

      • 一、QGraphicsView相关整理
      • 二、QGraphicsView架构下实时鼠标绘制图形
        • 2.1 鼠标拖拽绘图说明
        • 2.2 记录图形第一个绘制点
        • 2.3 实时获取鼠标最新位置并绘图
        • 2.4 释放绘制点,绘制最终图形
      • 三、QGraphicsView 在鼠标点击处进行放大缩小

一、QGraphicsView相关整理

项目中频繁地使用了QGraphicsView相关的类
(1)继承QGraphicsView,改写下面的protected成员函数进行自定义操作:

protected:
    void keyPressEvent(QKeyEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void paintEvent(QPaintEvent * event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);
    void wheelEvent(QWheelEvent *event);

使用中注意,如果想使QGraphicsView中已定义的操作任然有效,则需要在函数定义代码中添加下列语句, 以便实现父类已经是实现的默认操作。

QGraphicsView::keyPressEvent(event);
QGraphicsView::mousePressEvent(event);
QGraphicsView::mouseMoveEvent(event);
QGraphicsView::paintEvent(event);
QGraphicsView::mouseDoubleClickEvent(event);
QGraphicsView::wheelEvent(event);

(2) 可创建QGraphicsScene对象添加到QGraphicsView对象中(setScene(QgraphicsScene* scene)),可以使用同样的方法继承QGraphicsScene进行自定义操作;

(3) QGraphicsView中有**horizontalScrollBar()verticalScrollBar()**可以返回视图中的滚动条,下面的代码可以设置滚动条的显示模式

m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

// 设置在视图中进行拖动
setDragMode(QGraphicsView::ScrollHandDrag);

(4)当使用自定义的右键选择菜单时,需要下面的语句,在槽函数on_graphicsView_customContextMenuRequested(QPoint) 中定义相关操作

m_graphicsView->setContextMenuPolicy (Qt::CustomContextMenu);
    connect(m_graphicsView,SIGNAL(customContextMenuRequested(QPoint)),this, SLOT(on_graphicsView_customContextMenuRequested(QPoint)));

(5)QGraphicsItem相关:
QGraphicsTextItem, QGraphicsLineItem, QGraphicsRectItem 三个Graphicsitem

QGraphicsTextItem *title = new QGraphicsTextItem();
title->setPlainText(name);
title->setPos(10, 10);
title->setFont(QFont(QString::fromLocal8Bit ("楷体"),15));
title->setDefaultTextColor(QColor(160, 160, 160));
title->setZValue(30);//设置图层

QGraphicsLineItem *linetemp = new QGraphicsLineItem();
QPen pen = linetemp->pen();
pen.setColor(QColor(81, 82, 84));
pen.setWidth(4);
linetemp->setPen(pen);
linetemp->setLine(QLineF(0, 0, 10,  10));
linetemp->setZValue (12);

QGraphicsRectItem* m_overAreaTop = new QGraphicsRectItem();
m_overAreaTop->setRect(0,0,10,10);
m_overAreaTop->setBrush(QBrush(QColor(64, 66, 68)));//填充色
m_overAreaTop->setPen(QPen(QColor(64, 66, 68)));//边框线
m_overAreaTop->setZValue(10);

每个item设置ZValue可以在对象重合时选择显示哪个对象显示在最前面。
可以通过boundingRect()获取item的边界框QRect类对象,并可以通过mapFromGlobal、mapRectToParent、mapRectToScene等进行坐标转换,最后通过QRect的contains()判断相关点的包含问题。

二、QGraphicsView架构下实时鼠标绘制图形

2.1 鼠标拖拽绘图说明

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

绘制矩形框的核心流程
第一步:鼠标左键点击,记录初始点击位置
第二步:在窗口中移动鼠标,实时获取鼠标拖动点,根据拖动点绘制指定形状
第三步:鼠标点击右键释放鼠标,绘制最终图形

在进行鼠标点击绘制的时候,为了兼容多个图形的实时绘制,这里,不只是用两个QPoint成员变量记录鼠标点,而是采取了vector<QPontF>容器存储的方式。
例如:三角形图形,需要三个点才能确定图形;曲线图形,是由N多个点才能确定图形;等等…

图形枚举类型 枚举类型 形状
Drawing_Normal无图形绘制
Drawing_Circular 圆形
Drawing_StraightLine 直线
Drawing_Rectangular 矩形
Drawing_Triangle 三角形
Drawing_ManyLineSegements多线段
Drawing_Curve 曲线
2.2 记录图形第一个绘制点

这里以Drawing_Rectangular为例
鼠标点击后才能获取当前点击点的位置,记录按下点操作应该是在鼠标的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.3 实时获取鼠标最新位置并绘图

鼠标想要实时绘制,在移动鼠标的mouseMoveEvent事件中操作的。

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

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();
}
2.4 释放绘制点,绘制最终图形

鼠标事件: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();   //如果当前正在绘制图形,直接清除
			}
		}
	}
}

三、QGraphicsView 在鼠标点击处进行放大缩小

使用QGraphicsView类的设置属性函数.在构造函数中增加下面两个函数即可。

ui->View_ImageOpro->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ui->View_ImageOpro->setResizeAnchor(QGraphicsView::AnchorUnderMouse);

setDragMode枚举值:

  • QGraphicsView::NoDrag,
  • QGraphicsView::RubberBandDrag
  • QGraphicsView::ScrollHandDrag
MyGraphicsView::MyGraphicsView()
{
    //设置ui控件属性
    setDragMode(QGraphicsView::NoDrag);
    scale_m = 1;                                //图形原始比例
    setStyleSheet("padding: 0px; border: 0px;");//无边框
    setMouseTracking(true);                    //跟踪鼠标位置
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);  //隐藏水平条
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);    //隐藏竖条
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    setResizeAnchor(QGraphicsView::AnchorUnderMouse);
    
}
void MyGraphicsView::wheelEvent ( QWheelEvent * event )
{
    if (event->modifiers() == Qt::CTRL){                  //按住ctrl键 可以放大缩小
        if((event->delta() > 0)&&(scale_m >= 50)) return; //最大放大到原始图像的50倍

		// 图像缩小到自适应大小之后就不继续缩小; 重置图片大小和位置,使之自适应控件窗口大小
        else if((event->delta() < 0)&&(scale_m <= 0.01)) return;
        else
        {
            // 当前放缩倍数;
            qreal scaleFactor = this->matrix().m11();
            scale_m = scaleFactor;
            int wheelDeltaValue = event->delta();
            if (wheelDeltaValue > 0) this->scale(1.2, 1.2); // 向上滚动,放大;
            else this->scale(1.0 / 1.2, 1.0 / 1.2);         // 向下滚动,缩小;
            update();
        }
    }    
}

QPainter鼠标绘制矩形,多边形:https://blog.csdn.net/Stone_OverLooking/article/details/112886734

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

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

相关文章

【C++】string的使用

目录 1、为什么学习string类&#xff1f; 2、标准库中的string类 2.1 string类 2.2 string类的常见接口声明 2.2.1 string类的常见构造 ​编辑 2.2.2 string类对象的访问及遍历操作 2.2.3 string类对象的容量操作 2.2.4 string类对象的修改操作 ​编辑 1、为什么学习s…

CERLAB无人机自主框架: 2-动态目标检测与跟踪

前言&#xff1a;更多更新文章详见我的个人博客主页【MGodmonkeyの世界】 描述&#xff1a;欢迎来到CERLAB无人机自主框架&#xff0c;这是一个用于自主无人飞行器 (UAV) 的多功能模块化框架。该框架包括不同的组件 (模拟器&#xff0c;感知&#xff0c;映射&#xff0c;规划和…

gemini国内能用吗

gemini国内能用吗 虽然 Gemini 的具体功能和性能还未完全公开&#xff0c;但基于 Google 在 AI 领域的强大背景和技术实力&#xff0c;已经火出圈了&#xff0c;很多小伙伴已经迫不及待想了解一下它有什么优势以及如何快速使用上 首先我们来讲一下gemini的优势 多模态能力&a…

美摄智能视频创作平台,满足企业个性化的创作需求

视频已成为企业传播信息、展示品牌、吸引客户的重要手段&#xff0c;传统的视频制作方式往往耗时耗力&#xff0c;且效果不佳。美摄科技凭借其深厚的技术积累和创新能力&#xff0c;推出了面向企业的智能视频创作平台解决方案&#xff0c;助力企业轻松实现高质量的视频制作与传…

5 CatBoost模型

目录 1 背景 2 原理 2.1 类别特征处理 2.1.1 传统目标编码&#xff1a; TS 2.1.2 Greedy TS 2.1.3 ordered TS编码 2.1.4 CatBoost处理Categorical features总结 2.2.预测偏移处理 2.2.1 梯度无偏估计 2.3 树的构建​​​​​​​ 3 优缺点 优点 4 代码 1 背景 终于…

OpenHarmony鸿蒙南向开发案例:【智能门铃】

样例简介 智能门铃通过监控来访者信息&#xff0c;告诉主人门外是否有人按铃、有陌生人靠近或者无人状态。主人可以在数字管家中远程接收消息&#xff0c;并根据需要进行远程取消报警和一键开锁。同时&#xff0c;也可以通过室内屏幕获取门外状态。室内屏幕显示界面使用DevEco…

【创建型模式】单例模式

一、单例模式概述 单例模式的定义&#xff1a;又叫单件模式&#xff0c;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。&#xff08;对象创建型&#xff09; 要点&#xff1a; 1.某个类只能有一个实例&#xff1b;2.必须自行创建这个实例&#xff1b;3.必须自行向整…

C语言 | 动态内存管理

目录&#xff1a; 1. 为什么要有动态内存分配 2. malloc和free 3. calloc和realloc 4. 常见的动态内存的错误 5. 动态内存经典笔试题分析 6. 柔性数组 1. 为什么要有动态内存分配 我们已经掌握的内存开辟方式有&#xff1a; int val 20; //在栈空间上开辟四个字节 cha…

MR-JE-70A 三菱MR-JE伺服驱动器(750W通用型)

三菱MR-JE伺服驱动器(750W通用型) MR-JE-70A外部连接,MR-JE-70A用户手册,MR-JE-70A 三相或单相AC220V三菱通用型伺服放大器750W&#xff0c;配套电机HG-SN52J-S100、HG-KN73J-S100。 MR-JE-70A参数说明&#xff1a;伺服驱动器通用型750W&#xff0c;三相或单相AC200V~240V 三…

C语言野指针【入门详解】

目录 一、什么是野指针 二、野指针的成因 2.1 指针未初始化 2.2 指针越界访问 2.3 指针指向的空间释放 三、如何规避野指针 3.1 初始化指针 3.2 小心越界访问 3.3 当指针不用时&#xff0c;及时置为空 3.4 避免返回局部变量的地址 *结语&#xff1a; 希望这篇关于指…

IM即时通讯软件,WorkPlus私有化部署全面支持信创环境

在数字化转型的浪潮中&#xff0c;政企单位对即时通讯(IM)软件的需求日益增长。然而&#xff0c;随着信息化程度的提高&#xff0c;数据安全和信息泄露风险也日益凸显。在这样的背景下&#xff0c;WorkPlus作为一款私有化部署的IM即时通讯软件&#xff0c;以其在安全性、管理便…

汇编语言——将BX中的无符号数和有符号数以二进制、八进制、十六进制、十进制形式输出

文章目录 将BX中的无符号数以二进制形式输出将BX中的无符号数以八进制形式输出将BX中的无符号数以十六进制形式输出将BX中的无符号数以十进制形式输出将BX中的有符号数以十进制形式输出 将BX中的无符号数以二进制形式输出 利用移位指令会影响CF&#xff0c;默认dl30h(数字0)&a…

时序深入之CPR(Clock Pessimism Removal)详解

目录 一、CPR概念 二、CPR的计算 三、CPR的开启关闭 四、CPR为0 ​五、参考资料 一、CPR概念 在时序报告的目标时钟路径中&#xff0c;会有一行数据clock pesssimism&#xff0c;第一次见可能都会对这个概念感到疑惑 同样在每条时序路径的summary中&#xff0c;clock pat…

自动化测试Selenium(4)

WebDriver相关api 定位一组元素 webdriver可以很方便地使用findElement方法来定位某个特定的对象, 不过有时候我们需要定位一组对象, 这时候就要使用findElements方法. 定位一组对象一般用于一下场景: 批量操作对象, 比如将页面上的checkbox都勾上. 先获取一组对象, 再在这组…

[最新]访问/加速StackOverFlow的方法

但是有很多问题都是在StackOverFlow上有现成的解决方案&#xff0c;而某度搜索引擎…前一页的回答互相抄袭&#xff0c;看着实在胀眼睛。 话不多说&#xff0c;解决办法&#xff1a; 直接访问插件商店下载插件&#xff08;最快捷方便&#xff0c;点点就行&#xff09;&#x…

Linux系统编程——权限概念和权限管理

目录 一&#xff0c;关于Shell 1.1 外壳程序 1.2 shell的作用 1.3 shell运行原理 二&#xff0c;权限概念 2.1 用户与权限 2.2 su&#xff08;用户切换指令&#xff09; ​编辑 2.3 提升指令权限和信任名单 三&#xff0c;文件权限 3.1 关于文件权限 3.2 文件访问者…

UG10.如何设置鼠标滚轮操作模型放大缩小方向?

UG10.如何设置鼠标滚轮操作模型放大缩小方向呢&#xff1f;看一下具体操作步骤吧。 首先打开UG10.软件&#xff0c;在主菜单栏选择【文件】下拉菜单&#xff0c;选择【实用工具】。 点击【用户默认设置】。 文章源自四五设计网-https://www.45te.com/45545.html 选中【基本环…

python语言零基础入门——变量与简单数据类型

目录 一、变量 1.创建变量 2.变量的修改 3.变量的命名 &#xff08;1&#xff09;常量 &#xff08;2&#xff09;标识符 &#xff08;3&#xff09;关键字 &#xff08;4&#xff09;命名规则 二、简单数据类型 1.变量的数据类型 2.数据类型 3.整型&#xff08;In…

中断的设备树修改及上机实验(按键驱动)流程

写在前面的话&#xff1a;对于 GPIO 按键&#xff0c;我们并不需要去写驱动程序&#xff0c;使用内核自带的驱动程序 drivers/input/keyboard/gpio_keys.c 就可以&#xff0c;然后你需要做的只是修改设备树指定引脚及键值。 根据驱动文件中的platform_driver中的.of_match_tabl…

C++之类和对象三

目录 拷贝构造函数 定义铺垫 浅拷贝 深拷贝 总结 拷贝构造函数 那在创建对象时&#xff0c;可否创建一个与一个对象一某一样的新对象呢&#xff1f; 定义铺垫 构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c…
最新文章