当前位置: 首页 > news >正文

《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用

前言:
我们需要先由一个 QGraphicsView,这个是UI显示的地方,也就是装满可见原色的Scene,然后需要一个QGraphicsScene 用来管理所有可见的界面元素,要实现UI功能,我们需要用各种从QGraphicsItem拼装成UI控件,并赋予他控件的逻辑。

简单的说,QGraphicsView代表视图,QGraphicsScene 代表场景,QGraphicsItem代表图形项,QGraphicsItem放在QGraphicsScene 中,QGraphicsScene 放在QGraphicsView中。

1、坐标关系
这是QGraphicsView,始终是以左上角为(0, 0)点,单位为像素
在这里插入图片描述
创建场景QGraphicsScene ,并放入视图中:

QGraphicsScene* _scene = new QGraphicsScene(); 
ui.graphicsView->setScene(_scene);

注意:如果设置scene的坐标和宽高则不能放在构造里,不然不起效果,设置图形项宽高和坐标也不能在构造设置。

scene的坐标怎么看?
先忽略坐标看scene宽高,如果scene宽高小于view宽高,scene默认放到view正中央,
如果scene宽高大于view宽高,view视窗自动出现滚轮,保证view宽高和scene宽高一致
如果scene宽高没有设置,scene中没放图形项前宽高为0,放入图形项后scene宽高会和图形项宽高保持一致且scene宽高和左上角坐标会随着图像同步变化,scene就等同于图像,scene宽高没有设置,scene默认左上角坐标为(0, 0),原点也在左上角。scene宽高没有设置,图像左上角坐标始终与scene左上角坐标重合。
在这里插入图片描述
然后看scene的(x, y)坐标,(x, y)坐标为scene左上角坐标,有点特别要注意,不管scene左上角坐标如何变化,scene整体始终处于view正中央。
如果scene的(x, y)为(0, 0),scene的原点也为(0, 0)
如果scene的(x, y)为(-scene->width() / 2, -scene->height() / 2),scene的原点在view正中央。
在这里插入图片描述
图像坐标系也是一个独立的坐标系,图像左上角默认为(0, 0)点,把图像放入scene,图像左上角坐标默认在scene的原点,设置图像左上角坐标

pixmapItem->setPos(-scene->width() / 2, -scene->height() / 2);

这样图像左上角和scene左上角重合。

下面草图中继续说明三者坐标关系:
在这里插入图片描述

2、view,scene和item三者坐标转换
在这里插入图片描述
上图中,图片和矩形都放在QGraphicsItem里,红点为图形项零点(0, 0),因为一旦有了QGraphicsItem,scene会和item重合,所以红点处也为scene零点坐标(0, 0),但区别在于红点往左边一点,sence依然有坐标比如(-1, 0),但item直接返回空,无法计算item坐标,view视图坐标一直都是view显示框左上角为零点。

通过鼠标事件可以拿到视图view的坐标,比如触发mousePressEvent事件:
视图view坐标:

QPoint nViewPoint = event->pos();

通过视图坐标转场景scene坐标:

QPointF fScenePoint = this->mapToScene(nViewPoint);

通过场景坐标转图形项item坐标:

QGraphicsItem* pItem = this->scene()->itemAt(fScenePoint, QTransform()); //图形项指针
if (NULL != pItem)
{QPointF fItemPoint = pItem->mapFromScene(fScenePoint);   //获取图形项坐标
}

注意:鼠标在不同的item上比如图片,画的多边形点击一下不仅可以拿到该图形项Item坐标,而且通过pItem拿到对应的item图形项指针!!!!!

获取场景scene中所有Item图形项指针:

QList<QGraphicsItem*> allItems = scene->items();

每个图形项都有一个type标识,可以根据这个标识判断该图形项是图片,矩形,圆等等:

if(allItems[0]->type() == QGraphicsLineItem::Type)//直线
else if(allItems[0]->type() == QGraphicsRectItem::Type)//	矩形
else if(allItems[0]->type() == QGraphicsSimpleTextItem::Type)//	文本
//......

3、在场景scene中绘制不同图形项
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有时候我们会遇到这样一个问题:
当我们重新继承一个图形项的类比如QGraphicsRectItem,在自定义类中添加更多的关于矩形的功能,创建矩形对象时却一直画不出矩形?
在这里插入图片描述
在这里插入图片描述
需要把自定义类强转为QGraphicsRectItem类在设置绘制参数即可画出矩形,如下所示。
在这里插入图片描述
通过如上方式画矩形,QGraphicsRectItem会调用自己的paint事件画出矩形,当drawRect继承QGraphicsRectItem,同时又重写了paint方法,假如在drawRect的paint事件里直接return,用上面方法画矩形后会调用drawRect的paint方法然后直接return,当然无法画出矩形。如果重写paint方法又想在重写的paint方法中调用QGraphicsRectItem的paint方法,可以在paint方法中加上

QGraphicsRectItem::paint(painter, option, widget);

这样可以在return之前调用父类的绘画方法画出矩形。

如果在drawRect类中重写paint方法,当我实现了用鼠标画矩形的功能,画出来的矩形用鼠标在矩形上点一下却拿不到矩形的item指针(如下)
在这里插入图片描述
原因在于drawRect继承了QGraphicsRectItem,想要显示矩形并能拿到item指针,需要在paint中把drawRect强转为QGraphicsRectItem指针,再把更新的矩形数据QRect设置到QGraphicsRectItem中,那么paint中最后面应该加上如下代码:
在这里插入图片描述
另一种原因看不到绘制的图形项:
在这里插入图片描述
这里先创建一个矩形设置到sence中,然后再把图片设置到sence,运行后只看到图片看不到画的矩形原因在于sence中的items会根据additem的顺序展示出来,运行程序后先展示矩形,然后展示图片,但图片会覆盖矩形,所以只能看到图片,并不是矩形没有了,如果先additem图片在additem矩形,这样先展示图片,然后会在图片上画出矩形,这样可以正确显示。

4、其他一些补充:
(1)界面变化触发resizeEvent事件,想要图像实时在scene正中央需要在resizeEvent中设置:

m_Scene->setSceneRect(m_PixmapItem->boundingRect());

(2)如果在构造中创建矩形或图片并显示(图片显示m_PixmapItem->setPixmap(pixmap);),运行程序后会显示在view的左上角,这时sence和item的(0,0)点在view的左上角。
在这里插入图片描述
如果先创建一个矩形不设置坐标和宽高先创建出来additem到sence,然后等界面运行后通过点击按钮item->setRect(0,0,100,100),这样矩形会显示在view正中间。
在这里插入图片描述
在这里插入图片描述

(3)对一个item图元可设置焦点,设置可选中,设置可移动

item->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsSelectable |QGraphicsItem::ItemIsMovable );

(4)如果图片很大直接用QPixmap加载有可能在界面上显示不出来,可以先把图片加载成QImage类型,然后再把QImage转为QPixmap即可显示。或者设置图片缓存为0,QPixmapCache::setCacheLimit(0)这个方法有待验证。

(5)图形项的各种事件

void mousePressEvent(QGraphicsSceneMouseEvent* event) 
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
void hoverEnterEvent(QGraphicsSceneHoverEvent* event);         //鼠标移入图形项
void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);         //鼠标移出图形项
void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);  //右击菜单事件

需要注意的是图形项中的鼠标移动事件mouseMoveEvent必须鼠标在图形项上按下移动才能触发,这里没有setMouseTrack设置。使用鼠标在图形项上移入移出事件,需要在构造中加入setAcceptHoverEvents(true);
还有一点需要注意:想要图形项中的事件有相应,必须在继承GraphicsView类中写好对应的事件并在事件中调用父事件使事件透传到item,比如在界面画了一个矩形,想要在矩形上右键进入contextMenuEvent事件,必须在继承的GraphicsView类中重写contextMenuEvent事件,并在事件中调用父类事件QGraphicsView::contextMenuEvent(event);

在这里插入图片描述

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

相关文章:

《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用

前言&#xff1a; 我们需要先由一个 QGraphicsView&#xff0c;这个是UI显示的地方&#xff0c;也就是装满可见原色的Scene&#xff0c;然后需要一个QGraphicsScene 用来管理所有可见的界面元素&#xff0c;要实现UI功能&#xff0c;我们需要用各种从QGraphicsItem拼装成UI控件…...

32 _ 字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?

从今天开始,我们来学习字符串匹配算法。字符串匹配这样一个功能,我想对于任何一个开发工程师来说,应该都不会陌生。我们用的最多的就是编程语言提供的字符串查找函数,比如Java中的indexOf(),Python中的find()函数等,它们底层就是依赖接下来要讲的字符串匹配算法。 字符串…...

TCP怎么实现可靠传输

链接 1&#xff0c;TCP头部的校验和保证获取正确数据&#xff0c;防篡改&#xff1b; 2&#xff0c;序列号和ACK确认机制同于管理数据包&#xff0c;对接收到的数据包进行确认&#xff0c;对没有接收到的数据包进行重传&#xff1b; 3&#xff0c;重传机制&#xff0c;包括超…...

C# new 和 override 的区别

在C#中子类继承抽象类的时候&#xff0c;new 和override都可以用来修饰子类方法&#xff0c;但两者之间是有区别的。 相同点&#xff1a; 它们都是子类在覆写基类方法时&#xff0c;修饰子类同名方法用的&#xff0c;都是为了隐藏基类的同名方法在实例化子类对象的时候&#…...

C++11『右值引用 ‖ 完美转发 ‖ 新增类功能 ‖ 可变参数模板』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2022 版本 17.6.5 文章目录 &#x1f307;前言&#x1f3d9;️正文1.右值引用1.1.什么是右值引用&#xff1f;1.2.move 转移资源1.3.左值引用 vs …...

在Windows以命令行方式根据文件名称搜索文件

对于cmd.exe&#xff0c;使用&#xff1a;dir /s /b filename.extension /s选项表示在子目录中搜索文件&#xff0c;/b选项表示仅显示文件名而不显示其他信息 对于PowerShell&#xff0c;使用&#xff1a;Get-ChildItem -Path “C:” -Recurse -Filter filename.extension -Re…...

asp.net数字档案管理系统VS开发sqlserver数据库web结构c#编程web网页设计

一、源码特点 asp.net 数字档案管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发。 asp.net数字档案系统1 应用技…...

数据挖掘 决策树

# 编码声明&#xff0c;并不是注释&#xff0c;而是一种特殊的源文件指令&#xff0c;用于指定文件的字符编码格式 # -*- coding: utf-8 -*-import pandas as pd # 提供了DataFrame等数据结构 from sklearn.tree import DecisionTreeClassifier, export_graphviz # 决策树分类…...

“技能兴鲁”职业技能大赛-网络安全赛项-学生组初赛 WP

Crypto BabyRSA 共模攻击 题目附件&#xff1a; from gmpy2 import * from Crypto.Util.number import *flag flag{I\m not gonna tell you the FLAG} # 这个肯定不是FLAG了&#xff0c;不要交这个咯p getPrime(2048) q getPrime(2048) m1 bytes_to_long(bytes(flag.e…...

[Android]修改应用包名、名称、版本号、Icon以及环境判断和打包

1.修改包名 在Android Studio中更改项目的包名涉及几个步骤&#xff1a; 打开项目结构: 在Android Studio中&#xff0c;确保您处于Android视图模式&#xff08;在左侧面板顶部有一个下拉菜单可以选择&#xff09;。 重命名包名: 在项目视图中&#xff0c;找到您的包名&…...

基于风驱动算法优化概率神经网络PNN的分类预测 - 附代码

基于风驱动算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于风驱动算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于风驱动优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…...

安全计算环境(设备和技术注解)

网络安全等级保护相关标准参考《GB/T 22239-2019 网络安全等级保护基本要求》和《GB/T 28448-2019 网络安全等级保护测评要求》 密码应用安全性相关标准参考《GB/T 39786-2021 信息系统密码应用基本要求》和《GM/T 0115-2021 信息系统密码应用测评要求》 1身份鉴别 1.1对登录的…...

【Hello Go】Go语言函数

Go语言函数 定义格式自定义函数无参数无返回值有参数无返回值不定参数列表有返回值有多个返回值 函数类型匿名函数和闭包延迟调用deferdefer和匿名函数结合使用 获取命令行参数 定义格式 函数是构成代码执行的逻辑结构 在Go语言中 函数的基本组成为 func关键字函数名参数列表…...

docker小技能:容器IP和宿主机IP一致( Nacos服务注册ip为内网ip,导致Fegin无法根据服务名访问 )

文章目录 I 预备知识1.1 Docker组成1.2 命名空间 (进程隔离)1.3 Docker的网络模式1.4 容器IP和宿主机IP一致1.5 容器时间和服务器时间的一致性II 常用命令2.1 案例:流水线docker 部署2.2 删除没有使用的镜像2.3 shell 不打印错误输出2.4 阿里云流水线/jenkins忽略shell步骤中…...

Android笔记:震动实现

Android震动可以通过Vibrator类实现。以下是一个简单的代码示例&#xff1a; 注&#xff1a;需要注意&#xff0c;震动需要在子线程中执行&#xff0c;所以应该在一个异步任务中执行上述代码&#xff0c;或者使用Handler等机制将其发送到主线程中进行执行。 1、在AndroidMani…...

CSDN每日一题学习训练——Java版(二叉搜索树迭代器、二叉树中的最大路径和、按要求补齐数组)

版本说明 当前版本号[20231115]。 版本修改说明20231115初版 目录 文章目录 版本说明目录二叉搜索树迭代器题目解题思路代码思路参考代码 二叉树中的最大路径和题目解题思路代码思路参考代码 按要求补齐数组题目解题思路代码思路参考代码 二叉搜索树迭代器 题目 实现一个二…...

WPF中有哪些布局方式和对齐方法

在WPF (Windows Presentation Foundation) 中&#xff0c;你可以使用多种方式来进行元素的对齐&#xff0c;这主要取决于你使用的布局容器类型。以下是一些最常用的对齐方式&#xff1a; HorizontalAlignment 和 VerticalAlignment 在大多数WPF元素上&#xff0c;你可以使用 Ho…...

【2012年数据结构真题】

41题 &#xff08;1&#xff09; 最坏情况下比较的总次数 对于长度分别为 m&#xff0c;n 的两个有序表的合并过程&#xff0c;最坏情况下需要一直比较到两个表的表尾元素&#xff0c;比较次数为 mn-1 次。已知需要 5 次两两合并&#xff0c;故设总比较次数为 X-5, X 就是以 N…...

k8s_base

应用程序在服务器上部署方式的演变,互联网发展到现在为止 应用程序在服务器上部署方式 历经了3个时代1. 传统部署 优点简单 缺点就是操作系统的资源是有限制的&#xff0c;比如说操作系统的磁盘&#xff0c;内存 比如说我8G&#xff0c;部署了3个应用程序&#xff0c;当有一天…...

2023年亚太杯APMCM数学建模大赛数据分析题MySQL的使用

2023年亚太杯APMCM数学建模大赛 以2022年C题全球变暖数据为例 数据分析&#xff1a; 以2022年亚太杯数学建模C题为例&#xff0c;首先在navicat建数据库然后右键“表”&#xff0c;单击“导入向导”&#xff0c;选择对应的数据格式及字符集进行数据导入 导入之后&#xff0c…...

HsMod终极指南:5步打造你的专属炉石传说模改体验

HsMod终极指南&#xff1a;5步打造你的专属炉石传说模改体验 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod HsMod是一款基于BepInEx框架的炉石传说模改插件&#xff0c;为玩家提供全面的游戏体验…...

Claude Code本地安装与配置国产智谱模型 (保姆级教程)

目录 一、安装 二、验证安装完整性 三、绕过区域限制协议 1. 创建专属启动脚本 2. 配置系统环境变量 3. 通过脚本启动 四、配置国产智普模型 今天给大家带来一期非常实用的 AI 工具部署教程。作为开发者&#xff0c;善用 AI 工具能极大提升我们的日常编码和解决问题的效…...

Starry Night Art Gallery效果展示:黄金渐变按钮交互+实时生成反馈

Starry Night Art Gallery效果展示&#xff1a;黄金渐变按钮交互实时生成反馈 1. 沉浸式艺术体验&#xff1a;当AI遇见文艺复兴 想象一下&#xff0c;你走进的不是一个冰冷的AI工具界面&#xff0c;而是一座数字艺术殿堂。四周是深邃的墨蓝色背景&#xff0c;如同梵高笔下的夜…...

MongoDB(70)如何使用副本集进行备份?

使用副本集进行备份是一个常见的MongoDB备份策略&#xff0c;因为副本集提供了数据冗余和高可用性。通过从副本集中读取数据&#xff0c;可以在不影响主节点的情况下进行备份。以下是详细的步骤和示例代码&#xff0c;展示如何使用 MongoDB 副本集进行备份。方法一&#xff1a;…...

Cursor Composer 2 技术报告拆解:MoE 预训练、RL 环境设计与 CursorBench 基准的工程实践

在生产级代码仓库里&#xff0c;一个 AI Agent 面对的往往不是“实现某个功能”这样清晰的任务&#xff0c;而是“新特性上线后出现诡异 bug&#xff0c;日志里只有 954 个 JSON 响应&#xff0c;栈踪迹完全不可靠”。它必须自己跨文件定位、写启发式检测器、调参避免误报&…...

终极指南:NanoVG渲染管线深度解析与抗锯齿技术实战

终极指南&#xff1a;NanoVG渲染管线深度解析与抗锯齿技术实战 【免费下载链接】nanovg Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations. 项目地址: https://gitcode.com/gh_mirrors/na/nanovg NanoVG是一款基于OpenGL的轻量级抗锯…...

毕业设计实战:基于SSM+JSP的家纺用品销售管理系统设计与实现全攻略

毕业设计实战&#xff1a;基于SSMJSP的家纺用品销售管理系统设计与实现全攻略 在开发“家纺用品销售管理系统”这套毕设时&#xff0c;我曾因“订单管理与商家库存脱节”踩过一个关键坑。初期设计时&#xff0c;我将“用户下单”和“商家库存扣减”视为两个独立操作&#xff0c…...

AutoGen Studio效果展示:看Qwen3-4B如何协作完成网页设计

AutoGen Studio效果展示&#xff1a;看Qwen3-4B如何协作完成网页设计 1. AutoGen Studio简介 AutoGen Studio是一个基于微软AutoGen框架开发的低代码界面工具&#xff0c;它让构建和组合AI代理变得简单直观。通过这个平台&#xff0c;你可以快速创建多个AI代理&#xff0c;为…...

别再手动敲命令了!用PyCharm自带功能一键创建Linux桌面快捷方式(附手动配置备份方案)

告别终端&#xff1a;PyCharm内置工具3秒生成Linux桌面快捷方式&#xff08;附应急手动方案&#xff09; 每次打开PyCharm都要在终端输入一长串路径&#xff1f;作为开发者&#xff0c;我们的时间应该花在创造价值上&#xff0c;而不是重复输入命令。JetBrains早就为Linux用户准…...

保姆级教程:手把手教你用GLM-4v-9b搭建图片问答机器人

保姆级教程&#xff1a;手把手教你用GLM-4v-9b搭建图片问答机器人 你是不是经常遇到这样的情况&#xff1a;看到一张复杂的图表&#xff0c;想快速了解里面的数据含义&#xff1b;或者收到一张产品图&#xff0c;想知道它的具体型号和功能&#xff1b;又或者辅导孩子作业时&am…...