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坐标。

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

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

相关文章

C语言数据结构(11)——归并排序

欢迎来到博主的专栏C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 归并排序两个有序数组的合并归并归并排序 归并排序的代码 归并排序 两个有序数组的合并 当前有两个有序数组arr1和arr2&#xff0c;我们创建一个可以容纳arr1和arr2同等元素个数的新数组arr。 让一个…

蓝桥杯 经验技巧篇

1. 注意事项 &#x1f468;‍&#x1f3eb; 官方通知 &#x1f468;‍&#x1f3eb; 资料文档 时间&#xff1a;4月13日 9:00~13:00 &#xff08;时长 4小时&#xff09;物品 准考证&#xff08;赛前一周开放下载&#xff0c;自行打印&#xff09;学生证身份证笔、水、外套&a…

DDIM,多样性与运行效率之间的trade off

DDPM的重大缺陷在于其在反向扩散的过程中需要逐步从 x t x_t xt​倒推到 x 0 x_0 x0​&#xff0c;因此其推理速度非常缓慢。相反&#xff0c;DDPM的训练过程是很快的&#xff0c;可以直接根据 x 0 x_0 x0​到 x t x_t xt​添加的高斯噪声 ϵ \epsilon ϵ完成一次训练。 为了解…

springboot整合ShardingSphere分库分表并插入1kw条记录

目录 一&#xff0c;数据分片 二&#xff0c;水平分片 三&#xff0c;创建数据库表 四&#xff0c;springboot项目导入依赖 五&#xff0c;创建类 六&#xff0c;bug bug放到最后了。 一&#xff0c;数据分片 数据分片指按照某个维度将存放在单一数据库中的数据分散地存…

(学习日记)2024.04.06:UCOSIII第三十四节:互斥量函数接口讲解

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

【Hadoop技术框架-MapReduce和Yarn的详细描述和部署】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;今天的内容主要是Hadoop的后两个组件&#xff1a;MapReduce和yarn的相关内容。同时还有Hadoop的完整流程。希望对大家有所帮助。感谢大家关注点赞。 &#x1f49e;&#x1f49e;前路漫漫&…

香港科技大学(广州)智能制造学域可持续能源与环境学域博士招生宣讲会——重庆大学专场(暨全额奖学金政策)

两个学域代表教授亲临现场&#xff0c;面对面答疑解惑助攻申请&#xff01;可带简历现场咨询和面试&#xff01; &#x1f4b0;一经录取&#xff0c;享全额奖学金1.5万/月&#xff01; 报名链接&#xff1a;https://www.wjx.top/vm/wmuN2ea.aspx# 地点&#xff1a;重庆大学A区…

观《你想活出怎样的人生》有感

《你想活出怎样的人生》 四月六号&#xff0c;和赵茜小美女观看了宫崎骏导演拍的《你想活出怎样的人生》&#xff0c;感受颇丰&#xff0c;特此写一篇文章以记之。 电影简介 《你想活出怎样的人生》是宫崎骏执导的动画电影&#xff0c;不仅是宫崎骏的复出之作&#xff0c;也…

ARP寻址过程

当知道目标的IP但是不知道目标的Mac地址的时候就需要借助ARP寻址获取目标的Mac地址&#xff0c;传输层借助四元组&#xff08;源IP源端口&#xff1a;目标IP目标端口&#xff09;匹配&#xff0c;网络层借助IP匹配&#xff0c;数据链路层则根据Mac地址匹配&#xff0c;数据传输…

77、WAF攻防——权限控制代码免杀异或运算变量覆盖混淆加密传参

文章目录 WAF规则webshell免杀变异 WAF规则 函数匹配 工具指纹 webshell免杀变异 php 传参带入 eval可以用assert来替换,assert也可以将字符串当作php代码执行漏洞 php 变量覆盖 php 加密 使用加密算法对php后门进行加密 php 异或运算 简化:无字符webshellP 无数字字母rc…

Open3D(C++) 鲁棒损失函数优化的ICP算法

目录 一、损失函数1、关于2、损失函数3、Open3D实现二、代码实现三、结果展示1、配准前1、配准后本文由CSDN点云侠原创,

11、子串-滑动窗口最大值

题解&#xff1a; 双端队列是一种特殊的队列&#xff0c;允许你在队列的两端进行插入和删除操作。在滑动窗口问题中&#xff0c;我们使用它来存储可能是当前窗口最大值的元素的索引。 维护队列的顺序&#xff1a; 当新元素进入窗口时&#xff0c;我们将它与队列尾部的元素进…

307k star, 免费的编程书籍 free-programming-books

307k star, 免费的编程书籍 free-programming-books 分类 开源分享 项目名: free-programming-books -- 各种编程语言免费学习资源 Github 开源地址&#xff1a; https://github.com/EbookFoundation/free-programming-books 查找页面&#xff08;英文&#xff09;&#xff…

在线代码生成器Mybaitis和Mybaitis Plus

功能 支持根据提供的数据信息自动找表和表字段可以单独生成某个文件可以按需生成多个文件(打包为 zip)常用的 vo 和 dto 支持字段自定义(支持多表字段合并)在非包的场景可以不输入 root 包支持批量多表生成支持 lombok 和 swaggerMybaitis和Mybaitis Plus 在页面样式上基本一样…

java流式计算Stream

java流式计算Stream 流(Stream)到底是什么呢? 是数据渠道&#xff0c;用于操作数据源&#xff08;集合、数组等&#xff09;所生成的元素序列。 “集合讲的是数据&#xff0c;流讲的是计算! ” 特点&#xff1a; Stream自己不会存储元素。 Stream不会改变源对象。相反&#x…

分享一份适合练手的软件测试实战项目

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

面试算法-152-螺旋矩阵

题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 解 class Solution {public List<Integ…

串口和 蓝牙模块HC08

串口基本认知 串行接口简称串口&#xff0c;也称 串行通信 接口或 串行通讯接口 &#xff08;通常指 COM 接口 &#xff09;&#xff0c;是采用串行通信方 式的 扩展接口 。串行 接口&#xff08;Serial Interface &#xff09;是指数据一位一位地顺序传送。其特点是 通信线路…

vulhub打靶记录——Corrosion2

文章目录 主机发现端口扫描ssh—22search openssh EXP web服务—8080目录扫描登录tomcat后台 提权切换用户查看用户权限寻找SUID命令破解登录密文 总结 主机发现 使用nmap扫描局域网内存活的主机&#xff0c;命令如下&#xff1a; nmap -sP 192.168.151.0/24192.168.151.1&am…

【LeetCode】894. 所有可能的真二叉树

文章目录 [894. 所有可能的真二叉树](https://leetcode.cn/problems/all-possible-full-binary-trees/)思路一&#xff1a;分治代码&#xff1a;思路二&#xff1a;记忆化搜索代码&#xff1a; 894. 所有可能的真二叉树 思路一&#xff1a;分治 1.递归&#xff0c;n1 时&#…