qt自定义窗口在拖动过程中出现抖动且拖动后位置看上去不对

自定义窗口拖动

  • 引言
  • 开发环境
  • 关键性代码
  • 运行结果
  • 原因分析
  • 改进代码
  • 运行结果
  • globalPos()
  • globalPosition()
  • 再次修改代码
  • 运行结果
  • 区别

引言

本文旨在一个问题的记录:自定义窗口拖动的过程中,窗口不能很好的跟随鼠标移动,此外会出现窗口拖动时抖动。
下面是上文描述的效果:

拖动时窗口抖动


本文针对上面的问题,找出解决方法,且说明为什么。

开发环境

使用QtCreator开发。其相关的Qt库使用Qt6.6.0。
在这里插入图片描述

关键性代码

这里只给出自定义窗口拖动功能需要的部分关键代码。

    //窗口拖动相关变量声明QPointF m_pressPos;//鼠标按下时位置QPointF m_topLeftPos;//自定义窗口左上角的位置bool m_isPress;//鼠标左键是否按下//功能函数定义
void QCustomWidget::mousePressEvent(QMouseEvent *event)
{qDebug()<<"mousePressEvent";if(event->button() == Qt::LeftButton){m_pressPos = event->position();//相对于接收事件的窗口或者项,事件发生时的位置坐标m_topLeftPos = geometry().topLeft();m_isPress = true;}qDebug()<<"m_pressPos="<<m_pressPos<<", m_topLeftPos="<<m_topLeftPos;QWidget::mousePressEvent(event);
}void QCustomWidget::mouseReleaseEvent(QMouseEvent *event)
{m_isPress = false;QWidget::mouseReleaseEvent(event);
}void QCustomWidget::mouseMoveEvent(QMouseEvent *event)
{qDebug()<<"mouseMoveEvent";if(m_isPress && event->type() == QEvent::MouseMove){QPointF nowPos= event->position();qDebug()<<"nowPos="<<nowPos;move(QPoint((m_topLeftPos + nowPos - m_pressPos).x(),(m_topLeftPos + nowPos - m_pressPos).y()));qDebug()<<"x:"<<(m_topLeftPos + nowPos - m_pressPos).x()<<",y:"<<(m_topLeftPos + nowPos - m_pressPos).y();}QWidget::mouseMoveEvent(event);
}

以上只给主要相关代码,看懂就行。

运行结果

按照上面的代码运行之后,其效果就是本文开头所述那样,窗口拖动过程中出现抖动,且窗口不能实时跟随鼠标。

原因分析

上述代码中,鼠标按下函数mousePressEvent的实现代码里,获取鼠标按下的位置,使用m_pressPos = event->position();即position()来得到鼠标按下的位置。position()获取的位置相对于其所在的窗口或图形项,一般用于图形视图框获取图形项的位置。

在以前可能没有问题,但是qt6中便明确指出:
在这里插入图片描述
当移动窗口来响应鼠标事件,使用globalPosition()来代替position()。

顺便来看一下pos()的官方描述:
在这里插入图片描述
返回相对于接收事件的窗口,鼠标光标所在的位置。Qt6让使用position()代替pos()。
经实践所知,使用pos()与position()获得的鼠标位置,在窗口拖动中都出现抖动或者窗口不能及时跟随鼠标移动的现象。

改进代码

将之前使用position()获取坐标位置的地方改为globalPos(),且将之前QPointF类型的变量 m_pressPos与m_topLeftPos改为QPoint 类型。因为globalPos()返回值类型为QPoint 。

    //窗口拖动QPoint m_pressPos;QPoint m_topLeftPos;bool m_isPress;void QCustomWidget::mousePressEvent(QMouseEvent *event)
{qDebug()<<"mousePressEvent";if(event->button() == Qt::LeftButton){m_pressPos = event->globalPos();m_topLeftPos = geometry().topLeft();m_isPress = true;}qDebug()<<"m_pressPos="<<m_pressPos<<", m_topLeftPos="<<m_topLeftPos;QWidget::mousePressEvent(event);
}void QCustomWidget::mouseReleaseEvent(QMouseEvent *event)
{m_isPress = false;QWidget::mouseReleaseEvent(event);
}void QCustomWidget::mouseMoveEvent(QMouseEvent *event)
{qDebug()<<"mouseMoveEvent";if(m_isPress && event->type() == QEvent::MouseMove){QPoint nowPos= event->globalPos();qDebug()<<"nowPos="<<nowPos;move(QPoint((m_topLeftPos + nowPos - m_pressPos).x(),(m_topLeftPos + nowPos - m_pressPos).y()));qDebug()<<"x:"<<(m_topLeftPos + nowPos - m_pressPos).x()<<",y:"<<(m_topLeftPos + nowPos - m_pressPos).y();}QWidget::mouseMoveEvent(event);
}

再去运行程序,就能够正常拖动窗口了,不会出现抖动和窗口不能及时跟随鼠标移动的情况。

运行结果

拖动窗口

globalPos()

关于函数globalPos(),官方给出的描述如下:
在这里插入图片描述
但发现官方也在Qt6中要求近可能不使用globalPos(),已经在Qt6被抛弃,避免在新的代码中使用。使用globalPosition().toPoint()来代替。

globalPosition()

官方的描述如下:
在这里插入图片描述
于是即使上述的globalPos()可以解决原来的窗口拖动时的抖动和窗口不能及时跟随鼠标移动问题,但还是使用globalPosition()来实现一下看看吧。

再次修改代码

将globalPos()改为globalPosition().toPoint()来获取鼠标的位置。

void QCustomWidget::mousePressEvent(QMouseEvent *event)
{qDebug()<<"mousePressEvent";if(event->button() == Qt::LeftButton){m_pressPos = event->globalPosition().toPoint();m_topLeftPos = geometry().topLeft();m_isPress = true;}qDebug()<<"m_pressPos="<<m_pressPos<<", m_topLeftPos="<<m_topLeftPos;QWidget::mousePressEvent(event);
}void QCustomWidget::mouseReleaseEvent(QMouseEvent *event)
{m_isPress = false;QWidget::mouseReleaseEvent(event);
}void QCustomWidget::mouseMoveEvent(QMouseEvent *event)
{qDebug()<<"mouseMoveEvent";if(m_isPress && event->type() == QEvent::MouseMove){QPoint nowPos= event->globalPosition().toPoint();qDebug()<<"nowPos="<<nowPos;move(QPoint((m_topLeftPos + nowPos - m_pressPos).x(),(m_topLeftPos + nowPos - m_pressPos).y()));qDebug()<<"x:"<<(m_topLeftPos + nowPos - m_pressPos).x()<<",y:"<<(m_topLeftPos + nowPos - m_pressPos).y();}QWidget::mouseMoveEvent(event);
}

运行结果

其结果与使用globalPos()一样,都解决了窗口拖动时的抖动和不能及时跟随鼠标移动的问题。

区别

下面为pos(),globalPos(),globalPosition(),position()的区别:

pos():
这个函数返回控件在其父控件坐标系中的位置。

返回一个QPoint对象,表示控件左上角相对于其父控件的x和y坐标。
如果控件没有父控件(即它是一个顶级窗口),则pos()返回的是相对于屏幕的坐标。

globalPos():
这个函数返回控件在全局屏幕坐标系中的位置。
同样返回一个QPoint对象,但表示的是控件左上角相对于整个屏幕的x和y坐标。
这对于顶级窗口和子控件都适用,因为它总是返回屏幕上的绝对位置。

globalPosition():
这个函数与globalPos()的功能基本相同, 都返回控件在全局屏幕坐标系中的位置。

返回的也是QPoint对象,表示控件在屏幕上的绝对位置。
在某些版本的Qt中,globalPosition()可能是globalPos()的同义词或别名。Qt6之后推荐使用globalPosition()。

position():
这个函数通常用于QGraphicsItem,在Qt的图形视图框架中。

它返回该图形项在其父项或场景中的位置。
返回一个QPointF对象,表示图形项左上角的x和y坐标。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯赛前模拟

A-似巨龙高歌 题意 对考试的名次重新排序&#xff0c;使得进步最大的进步名次最少。 思路 按照名次从小到大进行排序&#xff0c;这样保证了进步的名次最少&#xff0c;从而取进步的最大值。 代码 #include<bits/stdc.h> #define PII pair<int,int> using n…

Kubernetes(k8s)监控与报警(qq邮箱+钉钉):Prometheus + Grafana + Alertmanager(超详细)

Kubernetes&#xff08;k8s&#xff09;监控与报警&#xff08;qq邮箱钉钉&#xff09;&#xff1a;Prometheus Grafana Alertmanager&#xff08;超详细&#xff09; 1、部署环境2、基本概念简介2.1、Prometheus简介2.2、Grafana简介2.3、Alertmanager简介2.4、Prometheus …

绿联 安装火狐浏览器(Firefox),支持访问路由器

绿联 安装火狐浏览器&#xff08;Firefox&#xff09;&#xff0c;支持访问路由器 1、镜像 linuxserver/firefox:latest 前置条件&#xff1a;动态公网IP。 已知问题&#xff1a; 直接输入中文时&#xff0c;不能完整输入&#xff0c;也可能输入法无法切换到中文&#xff0c;可…

【阿里淘天笔试题汇总】2024-04-10-阿里淘天春招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新淘天近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f…

Golang教程四(协程,channel,线程安全,syncMap)

目录 一、Goroutine和channel Goroutine Channel 发送和接收操作 缓冲 Channel 关闭 Channel 使用 Channel 进行同步 Select语句 协程超时处理 方法一&#xff1a;使用context.Context 方法二&#xff1a;使用time.Timer/time.Ticker 二、线程安全与sync.Map 线程安…

Vue3大事件项目1 登录注册验证

创建项目 引入 element-ui 组件库 登录&#xff1a;注册样式准备之后&#xff0c;配置校验规则&#xff08;4个条件&#xff1a;一数据、二规则&#xff09; 1. 校验相关 (1) 给当前表单绑上整个的数据对象&#xff1a;el-form > :model"ruleForm" 绑…

二叉树总结

递归返回值 1、如果需要搜索整棵二叉树且不用处理递归返回值&#xff0c;递归函数就不要返回值。 2、如果需要搜索整棵二叉树且需要处理递归返回值&#xff0c;递归函数就需要返回值。 3、如果要搜索其中一条符合条件的路径&#xff0c;那么递归一定需要返回值&#xff0c;…

Notepad++软件安装及配置说明

Notepad是 Windows操作系统下的一套文本编辑器&#xff0c;有完整的中文化接口及支持多国语言编写的功能。 Notepad功能比 Windows自带记事本强大&#xff0c;除了可以用来制作一般的纯文字说明文件&#xff0c;也十分适合编写计算机程序代码。Notepad不但可以显示行号&#xf…

1572. 【基础赛】涂色(paint)

1572. 【基础赛】涂色&#xff08;paint&#xff09; (Input: paint.in, Output: paint.out) 时间限制: 2 s 空间限制: 256 MB 具体限制 题目描述 Introl获得了一个N行的杨辉三角&#xff0c;他将每行中值为奇数的位置涂为了黑色。 Chihiro将提出M次询问&#xff0c;在第L…

Day2 字符串哈希KMP

字符串哈希 KMP 基本 字符串哈希 理论 将一个字符串转成一个数字&#xff0c;可以快速比较两个字符串是否相同等。要求为&#xff1a;相同字符串哈希值相同&#xff0c;不同字符串哈希值尽量不相同。 映射方法通常采用多项式哈希方法&#xff0c;很像进制转换。假设字符串为…

Tomcat服务

Tomcat服务 安装 安装java环境 yum install -y java-1.8.0-openjdk java -version # 看是否成功安装Tomcat&#xff0c;这里以apache-tomcat-8.0.30.tar.gz为例 tar -xvf apache-tomcat-8.0.30.tar.gz -C /usr/local/ mv /usr/local/apache-tomcat-8.0.30 /usr/local/tomc…

萝卜大杂烩 | 10 个杀手级的 Python 自动化脚本

本文来源公众号“萝卜大杂烩”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;10 个杀手级的 Python 自动化脚本 重复性任务总是耗时且无聊&#xff0c;想一想你想要一张一张地裁剪 100 张照片或 Fetch API、纠正拼写和语法等工作…

ELK日志

​​​​​​​

HJ53 杨辉三角的变形(基础数学,生成数组不行,会越界,使用规律)

第一种方法&#xff1a; 生成杨辉三角的方法不行&#xff0c;会出现越界&#xff0c; 数组从[0][0]开始&#xff0c;i行j列 只看列 每一行的最右侧坐标为2*i,下坐标为 0&#xff0c; 0&#xff0c;1&#xff0c;2 0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4 … …

MongoDB聚合运算符:$not

文章目录 语法使用举例 $not聚合运算符用于将指定布尔表达式的值取反&#xff0c;比如&#xff0c;表达式的值为 true&#xff0c; $not返回 false&#xff1b;表达式的值为 false&#xff0c; $not则返回 true。 语法 { $not: [ <expression> ] }使用 除false外…

革命性突破:Stability AI发布全新12B参数Stable LM 2模型,颠覆AI界!

Stability AI已推出其Stable LM 2语言模型系列的最新成员&#xff1a;一个120亿参数的基础模型和一个经过指令调优的变体。这些模型在七种语言上训练&#xff0c;包括英语、西班牙语、德语、意大利语、法语、葡萄牙语和荷兰语&#xff0c;训练数据达到了令人印象深刻的两万亿个…

Linux:动态库加载、编址

目录 一、库的概念 二、动静态库的加载 2.1绝对编址与相对编址 2.1一般程序的加载 三、动态库的加载 一、库的概念 库默认就是一个磁盘级文件&#xff0c;所以在执行代码时&#xff0c;库和可执行程序都会被加载到内存中&#xff0c;从原理上&#xff0c;库函数的调用依旧…

结构型模式--1.适配器模式【托尼托尼·乔巴】

1. 翻译家 在海贼王中&#xff0c;托尼托尼乔巴&#xff08;Tony Tony Chopper&#xff09;是草帽海贼团的船医&#xff0c;它本来是一头驯鹿&#xff0c;但是误食了动物系人人果实之后可以变成人的形态。 乔巴吃了恶魔果实之后的战斗力暂且抛开不谈&#xff0c;说说它掌握的第…

[C++][算法基础]树的重心(树图DFS)

给定一颗树&#xff0c;树中包含 n 个结点&#xff08;编号 1∼n&#xff09;和 n−1 条无向边。 请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 重心定义&#xff1a;重心是指树中的一个结点&#xff0c;如果将这个点删除后&a…

PostgreSQL入门到实战-第十四弹

PostgreSQL入门到实战 PostgreSQL数据过滤(七)官网地址PostgreSQL概述PostgreSQL中BETWEEN 命令理论PostgreSQL中BETWEEN 命令实战更新计划 PostgreSQL数据过滤(七) BETWEEN运算符允许您检查值是否在值的范围内。 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容…