Qt关于平滑滚动的使用QScroller及QScrollerProperties类说明

一、触控时代的滚动工具:QScroller类设计介绍

1.1 从机械滚轮到数字惯性

在触控设备普及前,滚动操作如同老式打字机的滚轴,只能通过鼠标滚轮或滚动条进行离散式控制。QScroller的出现如同给数字界面装上了"惯性飞轮",通过模拟物理上的动量守恒定律,让滚动操作具备以下特性:

  • 速度传递:滑动速度决定滚动距离;
  • 动态衰减:摩擦系数影响停止时间;
  • 边界弹性:类似橡皮筋的越界回弹效果;

1.2 类关系拓扑图

QScroller ────┬── QScrollerProperties 
              ├── QScrollEvent 
              └── QScrollPrepareEvent 

QScroller作为控制器,通过QScrollerProperties配置物理参数,生成QScrollEvent事件以驱动界面的刷新。

二、核心类深度解析

2.1 QScroller类:滚动引擎

关键方法说明:

// 启用控件手势支持(核心入口)
static QScroller *QScroller::grabGesture(
    QObject *target, 
    QScroller::GestureType gestureType = TouchGesture 
);

//检查指定的目标对象是否已经关联了 QScroller 实例
static bool hasScroller(QObject *target) ;

//使指定的目标对象停止捕获指定类型的滚动手势
static void ungrabGesture(QObject *target, 
QScroller::ScrollerGestureType gestureType);

// 获取当前滚动状态 
QScroller::State state() const; 
 
// 滚动到指定区域(带动画)
void scrollTo(const QVector2D &pos, 
             qreal scrollTime = 0);
 
// 确保子控件可见(自动计算滚动路径)
void ensureVisible(const QRectF &rect, 
                  qreal xmargin = 0.1, 
                  qreal ymargin = 0.1);

//设置滚动器的属性,如滚动速度、摩擦力、弹性等
void setScrollerProperties(const QScrollerProperties &properties);

//启动滚动器,开始滚动操作
void start();

//停止滚动器,终止滚动操作
void stop();

//设置水平方向的捕捉位置。当滚动到这些位置时,滚动器会自动对齐到这些位置。
void setSnapPositionsX(const QList<qreal> &positions);

//设置垂直方向的捕捉位置。当滚动到这些位置时,滚动器会自动对齐到这些位置。
void setSnapPositionsY(const QList<qreal> &positions);

手势类型枚举:

enum GestureType {
    TouchGesture,        // 触摸手势 
    LeftMouseButtonGesture, // 左键拖拽
    RightMouseButtonGesture // 右键拖拽(特殊场景)
};

2.2 QScrollerProperties:设置和调整配置参数

这个类就像汽车的"悬挂调校系统"调节汽车引擎一样,专门调整设置QScroller类的配置参数,包含几十个可配置参数,主要有:

QScrollerProperties properties;

//设置滚轮滚动过程中画面的帧率,帧率越高看着越舒服,帧率越低画面越跳动
properties.setScrollMetric(QScrollerProperties::FrameRate,QScrollerProperties::Fps30);
//设置平滑速度,当滑动完手离开屏幕后,进行平滑滑动的速度,此值应介于0和1之间。值越小,速度越慢。但我试过实际没太明显的区别
properties.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor,0.3);
//设置鼠标释放后滚动到停止时的运动曲线,参数为QEasingCurve类型,不能设置为QEasingCurve::Type类型,不会隐式转换
properties.setScrollMetric(QScrollerProperties::ScrollingCurve,QEasingCurve::OutQuad);
//设置移动阀值(按下后需要移动最少距离后,触发滑动),用来避免误操作
properties.setScrollMetric(QScrollerProperties::DragStartDistance,0.003);
//设置减速因子,值越大,减速越快,进而会影响点击释放后滚动的距离。对于大多数类型,该值应在0.1到2.0的范围内
properties.setScrollMetric(QScrollerProperties::DecelerationFactor,0.4);
//设置当运动方向与某一个轴的角度小于该设定值(0~1)时,则限定只有该轴方向的滚动,一般就用0.5,两个轴都是,不然要么区域重叠,要么区域漏掉
properties.setScrollMetric(QScrollerProperties::AxisLockThreshold,0.5);
//自动滚动过程中,鼠标点击操作会停止当前滚动,当速度大于该设定(m/s)时,鼠标事件不会传递给目标即不会停止滚动
properties.setScrollMetric(QScrollerProperties::MaximumClickThroughVelocity,0.5);
//与AcceleratingFlickSpeedupFactor配合使用。设置时间及加速因子
properties.setScrollMetric(QScrollerProperties::AcceleratingFlickMaximumTime ,3);
//与AcceleratingFlickMaximumTime配合使用,应>=1
properties.setScrollMetric(QScrollerProperties::AcceleratingFlickSpeedupFactor,2);
//设置自动滑动的最小速度,m/s,如果手势的速度小于该速度,则不会触发自动滚动,所以可以设置得小一些,防止手指轻微移动引起屏幕滚动
properties.setScrollMetric(QScrollerProperties::MinimumVelocity,0.2);
//设置自动滚动能达到得最大速度,m/s
properties.setScrollMetric(QScrollerProperties::MaximumVelocity,0.2);
//设置当拖拽过量时,释放后位置恢复所用时间(s)
properties.setScrollMetric(QScrollerProperties::OvershootScrollTime,0.2);
//设置滚动曲线的时间因子。设置滚动的时长,值越小,滚动时间越长
properties.setScrollMetric(QScrollerProperties::SnapTime,0.2);
//设置过量拖拽的距离占页面的比例,0~1,比如设置0.2,过量拖拽垂直最多移动高度的1/5
properties.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor,0.2);
//设置垂直向允许过量拖拽的策略,可以设置滚动条出现时开启、始终关闭、始终开启三种策略
properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy,QScrollerProperties::OvershootWhenScrollable);
//设置过量拖拽的移动距离与鼠标移动距离的比例,0~1,值越小表现出的阻塞感越强
properties.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor,0.2);
//设置自动滚动时允许的过量滚动距离比例
properties.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor,0.2);
//设置鼠标事件延迟时间,单位s。
properties.setScrollMetric(QScrollerProperties::MousePressEventDelay,1);

QScroller::scroller(ui->scrollArea)->setScrollerProperties(properties);

三、实现原理揭秘

3.1 事件处理流水线

sequenceDiagram 
    participant User 
    participant QScroller 
    participant Widget 
    
    User->>QScroller: 触摸/鼠标按下 
    QScroller->>Widget: 发送ScrollPrepare事件 
    Widget->>QScroller: 返回内容尺寸等信息 
    loop 每帧更新 
        QScroller->>QScroller: 计算物理运动参数 
        QScroller->>Widget: 发送ScrollEvent 
        Widget->>Widget: 更新显示位置 
    end 
    User->>QScroller: 释放操作 
    QScroller->>Widget: 触发惯性滚动 

3.2 物理模型公式

滚动位置计算采用改进型牛顿运动方程:

当前位置 = 初始位置 + 初速度 * t - 0.5 * 摩擦系数 * t²

其中摩擦系数通过QScrollerProperties::DecelerationFactor动态调整


四、实用代码示例

4.1 基础滑动实现

// 为QListWidget启用触控滑动 
QListWidget *list = new QListWidget(this);
QScroller *scroller = QScroller::scroller(list->viewport());
QScroller::grabGesture(list->viewport(), QScroller::TouchGesture);
 
// 配置滑动参数(类似手机APP的流畅感)
QScrollerProperties prop = scroller->scrollerProperties();
prop.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor,  0.6);
prop.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor,  0.3);
scroller->setScrollerProperties(prop);

4.2 高级分页滚动

// 相册浏览分页效果 
QScrollArea *gallery = new QScrollArea(this);
QScroller::grabGesture(gallery, QScroller::LeftMouseButtonGesture);
 
QScrollerProperties prop;
prop.setScrollMetric(QScrollerProperties::SnapPositionRatio,  1.0); // 整页吸附 
prop.setScrollMetric(QScrollerProperties::SnapTime,  0.5);         // 过渡动画时长 
QScroller::scroller(gallery)->setScrollerProperties(prop);

五、性能优化指南

  1. 渲染优化
// 启用像素级滚动(避免跳跃感)
listWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
  1. 内存管理
// 及时释放不再使用的滚动器
QScroller::ungrabGesture(scrollArea); // 类似断开刹车系统
  1. 动态调参技巧
// 根据设备类型切换参数 
#ifdef Q_OS_ANDROID 
    prop.setScrollMetric(...);  // 移动端优化参数 
#else 
    prop.setScrollMetric(...);  // 桌面端参数 
#endif 

结语:滚动交互的未来

随着Qt6对QScroller的持续优化,已经未来产品更趋向于实际流畅感的需求,作为开发使用人员,这几个方面的优化值得我们关注使用:

  1. 多指操作与3D滚动集成
  2. 基于AI的动态参数调优
  3. 与Vulkan渲染引擎的深度结合

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

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

相关文章

斩波放大器

目录 简介 自稳零斩波放大器 噪声 简介 双极性放大器的失调电压为25 μV&#xff0c;漂移为0.1 μV/C。斩波放大器尽管存在一些不利影 响&#xff0c;但可提供低于5 μV的失调电压&#xff0c;而且不会出现明显的失调漂移&#xff0c; 以下图1给出了基本的斩波放大器电路图。…

windows设置暂停更新时长

windows设置暂停更新时长 win11与win10修改注册表操作一致 &#xff0c;系统界面不同 1.打开注册表 2.在以下路径 \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键新建 DWORD 32位值&#xff0c;名称为FlightSettingsMaxPauseDays 根据需求填写数…

DIALOGPT:大规模生成式预训练用于对话响应生成

摘要 我们提出了一个大规模、可调节的神经对话响应生成模型&#xff0c;DIALOGPT&#xff08;对话生成预训练变换器&#xff09;。该模型训练于从2005年至2017年间Reddit评论链中提取的1.47亿次类似对话的交流&#xff0c;DIALOGPT扩展了Hugging Face的PyTorch变换器&#xff…

Mac端不显示正常用户名,变成192的解决方法

今天打开终端&#xff0c;本应该显示机器名的&#xff0c;但是此时显示了192。 问题原因&#xff1a; 当路由器的DNS使用默认的 192.168.1.1 或 192.168.0.1 的时候 Terminal 里的计算机名 会变成 localhost。当路由器的DNS使用自定义的 例如 运营商的DNS 或者 公共DNS的时候 …

SD 卡无屏安装启动树莓派5

最近想用一下树莓派5&#xff0c;拿出来一看&#xff0c;是 Micro-HMDI 的接口&#xff0c;手头正好没有这个接口线&#xff0c;便研究如何在没有显示屏的情况下&#xff0c;安装启动树莓派。 一、使用 Raspberry Pi Imager 烧录 SD 卡 选择 Raspberry Pi Imager 来烧录 SD 卡…

Xlua 编译 Windows、UWP、Android、iOS 平台支持库

Xlua 编译 Windows、UWP、Android、iOS 平台支持库 Windows&#xff1a; 安装 Visual Studio&#xff08;推荐 2017 或更高版本&#xff09; 安装 CMake&#xff08;https://cmake.org/&#xff09; macOS&#xff1a; 安装 Xcode 和命令行工具 安装 CMake 检查 cmake 是否安…

npm : 无法加载文件 E:\ProgramFiles\Nodejs\npm.ps1,因为在此系统上禁止运行脚本。

这个错误是因为 Windows 系统的 PowerShell 执行策略 限制了脚本的运行。默认情况下&#xff0c;PowerShell 的执行策略是 Restricted&#xff0c;即禁止运行任何脚本。以下是解决该问题的步骤&#xff1a; 1. 检查当前执行策略 打开 PowerShell&#xff08;管理员权限&#x…

基于专利合作地址匹配的数据构建区域协同矩阵

文章目录 地区地址提取完成的处理代码 在专利合作申请表中&#xff0c;有多家公司合作申请。在专利权人地址中&#xff0c; 有多个公司的地址信息。故想利用这里多个地址。想用这里的地址来代表区域之间的专利合作情况代表区域之间的协同、协作情况。 下图是专利合作表的一部分…

若依vue plus环境搭建

继前面文章若依系统环境搭建记录-CSDN博客 把ruoyi vue plus也摸索了下。 作者是疯狂的狮子&#xff0c;dromara/RuoYi-Vue-Plus 初始化文档&#xff1a;项目初始化&#xff0c;环境搭建的视频&#xff1a;RuoYi-Vue-Plus 5.0 搭建与运行_哔哩哔哩_bilibili 上来就列出了一…

在ubuntu如何安装samba软件?

我们在开发过程中&#xff0c;经常修改代码&#xff0c;可以安装samba文件来实现&#xff0c;把ubuntu的存储空间指定为我们win上的一个磁盘&#xff0c;然后我们在或者磁盘里面创建.c文件&#xff0c;进行代码修改和编写。samba能将linux的文件目录直接映射到windows&#xff…

论文阅读笔记:Deep Face Recognition: A Survey

论文阅读笔记&#xff1a;Deep Face Recognition: A Survey 1 介绍2 总览2.1 人脸识别组件2.1.1 人脸处理2.1.2 深度特征提取2.1.3 基于深度特征的人脸对比 3 网络结构和损失函数3.1 判别损失函数的演化3.1.1 基于欧式距离的损失3.1.2 基于角度/余弦边距的损失3.1.3 Softmax损失…

使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)

引言 在医疗领域&#xff0c;数据就是生命的密码&#xff0c;每一个数据点都可能蕴含着拯救生命的关键信息。特别是在 ICU 这样的重症监护场景中&#xff0c;医生需要实时、准确地了解患者的病情变化&#xff0c;以便做出及时有效的治疗决策。而随着医疗技术的飞速发展&#x…

Fiddler在Windows下抓包Https

文章目录 1.Fiddler Classic 配置2.配置浏览器代理自动代理手动配置浏览器代理 3.抓取移动端 HTTPS 流量&#xff08;可选&#xff09;解决抓取 HTTPS 失败问题1.Fiddler证书过期了 默认情况下&#xff0c;Fiddler 无法直接解密 HTTPS 流量。需要开启 HTTPS 解密&#xff1a; 1…

Anaconda安装 超详细版 (2025版)

目录 第一步&#xff1a;下载anaconda安装包 官网下载&#xff1a;Anaconda | Built to Advance Open Source AI 清华大学镜像站下载&#xff08;速度较快&#xff09; 第二步&#xff1a;安装anaconda 第三步&#xff1a;验证安装 扩展 创建conda基本环境 激活conda环…

想知道两轮差速方形底盘 URDF 咋做,ROS2 配 Rviz 咋显示吗?看这里!

视频讲解 想知道两轮差速方形底盘 URDF 咋做&#xff0c;ROS2 配 Rviz 咋显示吗&#xff1f;看这里&#xff01; 模型概述 一个方形底盘和两个差速驱动轮 URDF 代码 <?xml version"1.0" encoding"utf-8"?> <robot name"diff"> …

轻量化网络设计|ShuffleNet:深度学习中的轻量化革命

一、引言 在深度学习中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNN&#xff09;无疑是大家最耳熟能详的算法之一。自诞生以来&#xff0c;CNN 在图像分类、目标检测、语义分割等众多计算机视觉任务中取得了令人瞩目的成就&#xff0c;…

最好Wordpree+Apache+PHP安装教程

前提需要 PHP的安装最少需要7.4以上Mysql的安装&#xff0c;直接默认最新版就行APache服务器&#xff08;HTTP服务器&#xff0c;只有用这个你的软件才能在服务器上运行&#xff09; 安装apache 安装 sudo apt install apache2查看防火墙 sudo ufw app list如果有 Apache那…

Linux实操——在服务器上直接从百度网盘下载(/上传)文件

Linux Linux实操——在服务器上直接从百度网盘下载&#xff08;/上传&#xff09;文件 文章目录 Linux前言一、下载并安装bypy工具二、认证并授权网盘账号三、将所需文件转移至目的文件夹下四、下载文件五、上传文件六、更换绑定的百度云盘账户 前言 最近收到一批很大的数据&…

一周一个Unity小游戏2D反弹球游戏 - 移动的弹板(触屏版)

前言 上文中实现了用鼠标移动控制弹板的移动&#xff0c;本文将实现手指触屏时弹板跟随手指移动的功能&#xff0c;并通过使用Unity自带的Device Simulator Devices Package来验证和模拟触屏设备的使用场景。 安装Device Simulator Devices Package 打开Unity Package Manager&…

DeepSeek 开源狂欢周(一)FlashMLA:高效推理加速新时代

上周末&#xff0c;DeepSeek在X平台&#xff08;Twitter&#xff09;宣布将开启连续一周的开源&#xff0c;整个开源社区为之沸腾&#xff0c;全球AI爱好者纷纷为关注。没错&#xff0c;这是一场由DeepSeek引领的开源盛宴&#xff0c;推翻了传统推理加速的种种限制。这周一&…