当前位置: 首页 > 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…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...