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

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

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

相关文章

sqlmap requires ‘python-pymysql‘ third-party library

使用sqlmap进行udf提权报错&#xff1a; [14:06:04] [CRITICAL] sqlmap requires python-pymysql third-party library in order to directly connect to the DBMS MySQL. You can download it from https://github.com/PyMySQL/PyMySQL. Alternative is to use a package pyt…

高频SQL50题(基础班)-4

文章目录 主要内容一.SQL练习题1.1789-员工的直属部门代码如下&#xff08;示例&#xff09;: 2.610-判断三角形代码如下&#xff08;示例&#xff09;: 3.180-连续出现的数字代码如下&#xff08;示例&#xff09;: 4.1164-指定日期的产品价格代码如下&#xff08;示例&#x…

【深度学习】pytorch——常用工具模块

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 深度学习专栏链接&#xff1a; http://t.csdnimg.cn/dscW7 pytorch——常用工具模块 数据处理 torch.utils.data模块DatasetDataLoadersamplertorch.utils.data的使用 计算机视觉工具包 torchvisiontorchvision.d…

在Android上使用Jetpack Compose定制下拉刷新

在Android上使用Jetpack Compose定制下拉刷新 在Jetpack Compose中向LazyList添加下拉刷新非常简单。说真的&#xff0c;只需几行代码。然而&#xff0c;默认的外观和感觉并不是那么令人满意。我们希望做得更好一些&#xff0c;类似于iOS版本&#xff1a;当用户向下拉动列表时…

【解刊】IEEE(trans),中科院2区,顶刊,CCF-A类,圈外人别想投?

计算机类 • 好刊解读 今天小编带来IEEE旗下计算机领域好刊的解读&#xff0c;如有相关领域作者有意向投稿&#xff0c;可作为重点关注&#xff01;后文有真实发表案例&#xff0c;供您投稿参考~ 01 期刊简介 IEEE Transactions on Computers ☑️出版社&#xff1a;IEEE …

PayPal的CISO谈GenAI如何提高网络安全

在最近一个季度(2023财年第二季度)&#xff0c;PayPal报告收入为73亿美元&#xff0c;同比增长7%&#xff0c;5%的交易增长和37%的增值服务收入增长带来了强劲的季度业绩。截至2022年&#xff0c;PayPal的营收为275亿美元。 在进入PayPal之前&#xff0c;Keren创建了两家网络安…

地面沉降监测站可以监测什么?

随着城市化的飞速发展&#xff0c;地面沉降问题日益凸显。为了及时掌握土地沉降情况&#xff0c;确保人们安全&#xff0c;就需要借助地面沉降监测站的力量。 一、实时监测土地沉降 地面沉降监测站的核心功能是实时监测土地沉降。通过高精度GNSS位移监测站和先进的数据分析技术…

CS224W6.3——图深度学习

在这篇中&#xff0c;将介绍图神经网络的架构。关键思想是&#xff0c;在GNNs中&#xff0c;根据局部网络邻域生成节点嵌入。gnn通常由任意数量的层组成&#xff0c;而不是单层&#xff0c;以集成来自更大上下文的信息。介绍了如何使用gnn来解决优化问题&#xff0c;以及它强大…

vue3配置@别名

在项目开发中&#xff0c;通常我们是不写相对路径的&#xff0c;因为有些文件需要在不同的文件中使用&#xff0c;如果使用相对路径&#xff0c;那么我们每次去CV路径的时候就要重新修改。因此通常我们是写跟路径的&#xff0c;但是从头开始又太过于麻烦&#xff0c;因此我们使…

行情不好,程序员的路在哪里?

最近有人提问&#xff0c;行情不好&#xff0c;程序员的路在哪里&#xff1f;今天的文章从远程工作、市场和流量思维、新技术、自媒体几个维度来讲讲。 远程工作 如果你在二三线城市&#xff0c;机会比较少&#xff0c;可以考虑一下远程工作。找一份美国或欧洲的远程工作&…

【OpenVINO】基于 OpenVINO C# API 部署 RT-DETR 模型

基于 OpenVINO C# API 部署 RT-DETR 模型 1. RT-DETR2. OpenVINO3. 环境配置4. 模型下载与转换5. C#代码实现5.1 模型推理类实现1. 模型推理类初始化2. 图片预测API 5.2 模型数据处理类RTDETRProcess1. 定义RTDETRProcess2. 输入数据处理方法3. 预测结果数据处理方法 6. 预测结…

【实例分割】用自己数据集复现经典论文YOLACT

YOLACT&#xff1a;You Only Look At CoefficienTs &#x1f3c6;论文下载&#xff1a;paper &#x1f3c6;代码下载&#xff1a;code &#x1f3c6;论文详解&#xff1a;YOLACT 目录 &#x1f342;&#x1f342;1.安装环境 &#x1f342;&#x1f342;2.数据准备 &…

AIGC|如何将Milvus集成到LangFlow中?详细代码演示!

目录 一、基本介绍 二、修改langflow代码使其支持milvus 三、效果演示 langflow是一个LangChain UI&#xff0c;它提供了一种交互界面来使用LangChain&#xff0c;通过简单的拖拽即可搭建自己的实验、原型流。通过在langflow中引入Milvus&#xff0c;用户可以更方便地存储和…

Mac电脑安装打印机驱动

1.在打印机背面找到型号&#xff0c;当想要安装的驱动在官网找不到时可直接搜索该系列&#xff1a;比如MF系列 2.安装完成后需要添加打印机 当打印机和电脑在同一个WiFi下的时候查找打印机IP&#xff0c;输入IP后可以查到对应的打印机&#xff0c;添加后即可使用

动态库和静态库

目录 一、动态库和静态库二、静态库2.1 生成静态库2.2 库搜索路径 三、动态库3.1 生成动态库3.2 使用动态库3.3 运行动态库3.4 使用外部库3.5 库文件名称和引入库的名称 四、动静态库及周边知识一览图 一、动态库和静态库 静态库&#xff08;.a&#xff09;&#xff1a;程序在…

如何获取1688商品详情,价格,图片

1688是阿里巴巴旗下的B2B电子商务平台&#xff0c;主要面向国内的生产商和批发商。 通过获取到的跨境属性数据&#xff0c;可以了解到商品的跨境属性&#xff0c;例如商品的语言、原产地、适用场景等信息。这些数据可以帮助用户更好地了解商品的特点和质量&#xff0c;做出更明…

频谱测量---测量信号的功率

频谱测量 通道功率、带宽、均值频率、中位数频率、谐波失真。 使用 obw 和 powerbw 查找信号的 90% 占用带宽和 3-dB 带宽。计算功率谱的均值或中位数频率。估计给定频带上的功率。测量谐波失真。估计瞬时带宽、瞬时频率、频谱熵和谱峭度。 函数 功率和带宽 bandpowerBand…

【避雷选刊】Springer旗下2/3区,2个月录用!发文量激增,还能投吗?

计算机类 • 好刊解读 前段时间小编分析过目前科睿唯安数据库仍有8本期刊处于On Hold状态&#xff0c;其中包括4本SCIE、4本ESCI期刊&#xff08;&#x1f449;详情可见&#xff1a;避雷&#xff01;又有2本期刊被标记“On Hold”&#xff01;含中科院2区&#xff08;TOP&…

研究前沿 | Science:单细胞测序助力绘制迄今最完善的灵长类动物前大脑发育图谱

引言 大脑发育的关键分子机制在啮齿动物中已有所了解&#xff0c;但在灵长类动物中仍然不清楚&#xff0c;这限制了研究者对高级认知能力起源和功能障碍的理解。此外&#xff0c;在包括人类在内的灵长类动物中&#xff0c;关于轴突投射路径上的丘脑区域和皮层区域多样化的早期分…

优思学院|如何利用六西格玛提升自己的大格局?

首先&#xff0c;我想说大格局并不仅仅是一个概念&#xff0c;更是一种生活态度。拥有大格局的人通常能够超越日常琐事&#xff0c;将目光投向更广阔的未来。他们不会被小事困扰&#xff0c;而是将注意力集中在更大的目标和使命上。拥有大格局的人常常具备卓越的领导力和判断力…