qt浏览文件支持惯性

#include <QApplication>
#include <QListWidget>
#include <QScroller>
#include <QScrollerProperties>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建列表控件并添加示例项QListWidget listWidget;for (int i = 0; i < 100; ++i) {listWidget.addItem(QString("文件 %1").arg(i));}listWidget.resize(400, 300);listWidget.show();// 启用惯性滚动:触摸手势// QScroller::grabGesture(listWidget.viewport(), QScroller::TouchGesture);// 或者启用鼠标左键拖动惯性QScroller::grabGesture(listWidget.viewport(), QScroller::LeftMouseButtonGesture);// 获取Scroller对象并设置参数QScroller *scroller = QScroller::scroller(listWidget.viewport());QScrollerProperties properties = scroller->scrollerProperties();// 调整减速度因子(0~1,值越小惯性越长)properties.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.05);// 设置最小拖动触发距离(防止误触)properties.setScrollMetric(QScrollerProperties::DragStartDistance, 0.001);scroller->setScrollerProperties(properties);return app.exec();
}

示例二:

// inertialscroller.h
#ifndef INERTIALSCROLLER_H
#define INERTIALSCROLLER_H#include <QAbstractItemView>
#include <QEvent>
#include <QMouseEvent>
#include <QObject>
#include <QPointF>
#include <QScrollBar>
#include <QTableView>
#include <QTime>
#include <QTimer>
#include <QWheelEvent>/*** @brief 惯性滚动管理器类** 为QTableView或其他QAbstractItemView子类提供惯性滚动功能。* 追踪鼠标拖拽事件并在释放后应用速度衰减算法模拟惯性滚动效果。*/
class InertialScroller : public QObject
{Q_OBJECTpublic:/*** @brief 构造函数* @param view 需要添加惯性滚动功能的视图* @param parent 父对象*/explicit InertialScroller(QAbstractItemView *view, QObject *parent = nullptr);/*** @brief 析构函数*/~InertialScroller();/*** @brief 设置衰减系数,控制惯性滚动的衰减速度* @param factor 衰减系数(0.0-1.0),越小衰减越快*/void setDecelerationFactor(qreal factor);/*** @brief 设置惯性滚动的最大初始速度* @param speed 最大速度(像素/秒)*/void setMaxSpeed(qreal speed);/*** @brief 设置停止惯性滚动的最小速度阈值* @param threshold 速度阈值(像素/秒)*/void setStopThreshold(qreal threshold);/*** @brief 设置滚轮惯性滚动的强度系数* @param factor 强度系数,数值越大惯性效果越强*/void setWheelSpeedFactor(qreal factor);/*** @brief 启用或禁用滚轮惯性滚动* @param enable 是否启用*/void setWheelInertiaEnabled(bool enable);protected:/*** @brief 事件过滤器* 拦截视图的鼠标事件处理惯性滚动*/bool eventFilter(QObject *watched, QEvent *event) override;private:QAbstractItemView *m_view;                    // 关联的视图QTimer             m_timer;                   // 惯性滚动计时器QTime              m_lastTime;                // 上次事件时间QPointF            m_lastPos;                 // 上次鼠标位置QPointF            m_velocity;                // 当前速度(x和y方向)bool               m_isPressed     = false;   // 鼠标是否按下bool               m_isScrolling   = false;   // 是否正在滚动qreal              m_deceleration  = 0.95;    // 衰减系数(0.0-1.0)qreal              m_maxSpeed      = 2000.0;  // 最大速度(像素/秒)qreal              m_stopThreshold = 10.0;    // 停止阈值(像素/秒)QVector<QPointF>   m_positions;               // 最近的鼠标位置记录QVector<qint64>    m_timestamps;              // 最近的鼠标位置时间戳qreal              m_wheelSpeedFactor = 15.0;  // 滚轮速度系数bool               m_wheelInertiaEnabled = true; // 是否启用滚轮惯性private slots:/*** @brief 执行惯性滚动步骤*/void scrollStep();/*** @brief 开始惯性滚动*/void startScrolling(const QPointF &velocity);/*** @brief 停止惯性滚动*/void stopScrolling();
};#endif  // INERTIALSCROLLER_H
// inertialscroller.cpp
#include <QDateTime>
#include <QDebug>
#include <QtMath>#include "inertialscroller.h"InertialScroller::InertialScroller(QAbstractItemView *view, QObject *parent) : QObject(parent), m_view(view)
{// 安装事件过滤器m_view->viewport()->installEventFilter(this);// 初始化计时器m_timer.setInterval(16);  // 约60FPSconnect(&m_timer, &QTimer::timeout, this, &InertialScroller::scrollStep);// 初始化历史记录容器m_positions.reserve(10);m_timestamps.reserve(10);
}InertialScroller::~InertialScroller()
{if(m_view && m_view->viewport()){m_view->viewport()->removeEventFilter(this);}m_timer.stop();
}void InertialScroller::setDecelerationFactor(qreal factor)
{// 确保值在有效范围内m_deceleration = qBound(0.1, factor, 0.99);
}void InertialScroller::setMaxSpeed(qreal speed)
{m_maxSpeed = qMax(1.0, speed);
}void InertialScroller::setStopThreshold(qreal threshold)
{m_stopThreshold = qMax(1.0, threshold);
}void InertialScroller::setWheelSpeedFactor(qreal factor)
{m_wheelSpeedFactor = qMax(1.0, factor);
}void InertialScroller::setWheelInertiaEnabled(bool enable)
{m_wheelInertiaEnabled = enable;
}bool InertialScroller::eventFilter(QObject *watched, QEvent *event)
{if(watched != m_view->viewport())return false;switch(event->type()){case QEvent::MouseButtonPress: {QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);if(mouseEvent->button() == Qt::LeftButton){stopScrolling();m_isPressed = true;m_lastPos   = mouseEvent->pos();m_lastTime.start();// 清空历史记录m_positions.clear();m_timestamps.clear();// 记录初始位置和时间m_positions.append(mouseEvent->pos());m_timestamps.append(QDateTime::currentMSecsSinceEpoch());}break;}case QEvent::MouseMove: {if(m_isPressed){QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);QPointF      currentPos = mouseEvent->pos();// 计算移动距离QPointF delta = m_lastPos - currentPos;// 添加到历史记录m_positions.append(currentPos);m_timestamps.append(QDateTime::currentMSecsSinceEpoch());// 仅保留最近的5个记录点while(m_positions.size() > 5){m_positions.removeFirst();m_timestamps.removeFirst();}// 滚动视图QScrollBar *vScrollBar = m_view->verticalScrollBar();QScrollBar *hScrollBar = m_view->horizontalScrollBar();if(vScrollBar && vScrollBar->isVisible()){vScrollBar->setValue(vScrollBar->value() + delta.y());}if(hScrollBar && hScrollBar->isVisible()){hScrollBar->setValue(hScrollBar->value() + delta.x());}m_lastPos = currentPos;}break;}case QEvent::MouseButtonRelease: {if(m_isPressed){QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);if(mouseEvent->button() == Qt::LeftButton){m_isPressed = false;// 如果有足够的历史数据来计算速度if(m_positions.size() >= 2){// 使用最后几个点的平均速度QPointF totalVelocity(0, 0);int     count = 0;for(int i = 1; i < m_positions.size(); ++i){qint64 timeDelta = m_timestamps[i] - m_timestamps[i - 1];if(timeDelta > 0){QPointF posDelta = m_positions[i - 1] - m_positions[i];// 速度 = 距离/时间,单位为像素/秒QPointF velocity = posDelta * (1000.0 / timeDelta);totalVelocity += velocity;count++;}}if(count > 0){QPointF avgVelocity = totalVelocity / count;// 限制最大速度qreal speedX = qBound(-m_maxSpeed, avgVelocity.x(), m_maxSpeed);qreal speedY = qBound(-m_maxSpeed, avgVelocity.y(), m_maxSpeed);// 如果速度足够大,启动惯性滚动QPointF finalVelocity(speedX, speedY);qreal   speed = qSqrt(speedX * speedX + speedY * speedY);if(speed > m_stopThreshold){startScrolling(finalVelocity);}}}}}break;}case QEvent::Wheel: {// 如果滚轮惯性被禁用,不拦截事件if(!m_wheelInertiaEnabled){stopScrolling();return false;}// 处理鼠标滚轮事件产生惯性滚动QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);// 停止当前的惯性滚动stopScrolling();// 计算滚轮滚动的速度和方向QPoint pixelDelta = wheelEvent->pixelDelta();QPoint angleDelta = wheelEvent->angleDelta();// 优先使用像素增量,如果没有则使用角度增量QPointF scrollAmount;if(!pixelDelta.isNull()){scrollAmount = QPointF(pixelDelta);} else if(!angleDelta.isNull()){// 标准鼠标滚轮:角度转为像素(大约8度为一个标准滚动单位)scrollAmount = QPointF(angleDelta) / 8.0;}// 应用滚动方向(正数向下/右,负数向上/左)scrollAmount = -scrollAmount;// 缩放滚动量来创建合适的惯性效果QPointF velocity = scrollAmount * m_wheelSpeedFactor;// 如果速度足够大,开始惯性滚动qreal speed = qSqrt(velocity.x() * velocity.x() + velocity.y() * velocity.y());if(speed > m_stopThreshold){startScrolling(velocity);// 先手动执行一次滚动,让响应更快QScrollBar *vScrollBar = m_view->verticalScrollBar();QScrollBar *hScrollBar = m_view->horizontalScrollBar();if(vScrollBar && vScrollBar->isVisible() && !angleDelta.isNull()){vScrollBar->setValue(vScrollBar->value() + angleDelta.y() / 120 * vScrollBar->singleStep());}if(hScrollBar && hScrollBar->isVisible() && !angleDelta.isNull()){hScrollBar->setValue(hScrollBar->value() + angleDelta.x() / 120 * hScrollBar->singleStep());}return true;  // 拦截滚轮事件,自己处理}break;}default:break;}// 继续传递事件,不拦截return false;
}void InertialScroller::scrollStep()
{if(!m_isScrolling || m_isPressed)return;// 减速m_velocity *= m_deceleration;// 计算滚动距离qreal dx = m_velocity.x() * (m_timer.interval() / 1000.0);qreal dy = m_velocity.y() * (m_timer.interval() / 1000.0);// 应用滚动QScrollBar *vScrollBar = m_view->verticalScrollBar();QScrollBar *hScrollBar = m_view->horizontalScrollBar();if(vScrollBar && vScrollBar->isVisible()){vScrollBar->setValue(vScrollBar->value() + qRound(dy));}if(hScrollBar && hScrollBar->isVisible()){hScrollBar->setValue(hScrollBar->value() + qRound(dx));}// 如果速度足够小,停止滚动qreal speed = qSqrt(m_velocity.x() * m_velocity.x() + m_velocity.y() * m_velocity.y());if(speed < m_stopThreshold){stopScrolling();}
}void InertialScroller::startScrolling(const QPointF &velocity)
{if(m_isScrolling)return;m_velocity    = velocity;m_isScrolling = true;m_timer.start();
}void InertialScroller::stopScrolling()
{if(!m_isScrolling)return;m_timer.stop();m_isScrolling = false;m_velocity    = QPointF(0, 0);
}

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

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

相关文章

路径规划算法BFS/Astar/HybridAstar简单实现

借鉴本文所述代码简单实现一下BFS&#xff0c;Astar和HybridAstar路径规划算法&#xff0c;用于辅助理解算法原理。 代码在这里&#xff0c;画图用到了matplotlibcpp库&#xff0c;需要先装一下&#xff0c;然后直接在文件目录下执行如下代码即可运行&#xff1a; mkdir build…

get_the_category() 和 get_the_terms() 的区别

get_the_category() 和 get_the_terms() 是WordPress中用于获取文章分类的两个函数&#xff0c;但它们之间存在一些关键差异&#xff1a; get_the_category() 特定于分类&#xff1a;get_the_category() 函数专门用于获取文章的分类(category)。它返回一个包含所有分类对象的…

RocketMq的消息类型及代码案例

RocketMQ 提供了多种消息类型&#xff0c;以满足不同业务场景对 顺序性、事务性、时效性 的要求。其核心设计思想是通过解耦 “消息传递模式” 与 “业务逻辑”&#xff0c;实现高性能、高可靠的分布式通信。 一、主要类型包括 普通消息&#xff08;基础类型&#xff09;顺序…

maxkey单点登录系统

github地址 https://github.com/MaxKeyTop/MaxKey/blob/master/README_zh.md 1、官方镜像 https://hub.docker.com/u/maxkeytop 2、MaxKey:Docker快速部署 参考地址&#xff1a; Docker部署 | MaxKey单点登录认证系统 拉取docker脚本MaxKey: Dromara &#x1f5dd;️MaxK…

基于AI生成测试用例的处理过程

基于AI生成测试用例的处理过程是一个结合机器学习、自然语言处理&#xff08;NLP&#xff09;和领域知识的系统性流程。以下是其核心步骤和关键技术细节&#xff0c;以帮助理解如何利用AI自动化生成高效、覆盖全面的测试用例。 1. 输入分析与需求建模 目标 将用户需求、系统文…

《Java vs Go vs C++ vs C:四门编程语言的深度对比》

引言​​ 从底层硬件操作到云端分布式系统&#xff0c;Java、Go、C 和 C 四门语言各自占据不同生态位。本文从​​设计哲学​​、​​语法范式​​、​​性能特性​​、​​应用场景​​等维度进行对比&#xff0c;为开发者提供技术选型参考。 一、​​设计哲学与历史定位​​…

无损提速黑科技:YOLOv8+OREPA卷积优化方案解析(原理推导/代码实现/调参技巧三合一)

文章目录 一、OREPA核心思想与创新突破1.1 传统重参数化的局限性1.2 OREPA的核心创新二、OREPA实现原理与数学推导2.1 卷积核分解策略2.2 动态融合公式三、YOLOv8集成实战(完整代码实现)3.1 OREPA卷积模块定义3.2 YOLOv8模型集成3.3 训练与推理配置四、性能对比与实验分析4.1…

RestTemplate 发送的字段第二个大写字母变成小写的问题探究

在使用RestTemplate 发送http 请求的时候&#xff0c;发现nDecisonVar 转换成了ndecisonVar ,但是打印日志用fastjson 打印的没有问题&#xff0c;换成jackson 打印就有问题。因为RestTemplate 默认使用的jackson 作为json 序列化方式&#xff0c;导致的问题&#xff0c;但是为…

C#核心概念解析:析构函数、readonly与this关键字

&#x1f50d; 析构函数&#xff1a;资源清理的最后防线 核心作用 析构函数&#xff08;~ClassName&#xff09;在对象销毁前执行&#xff0c;专用于释放非托管资源&#xff08;如文件句柄、非托管内存&#xff09;。托管资源&#xff08;如.NET对象&#xff09;由GC自动回收…

FFmpeg中使用Android Content协议打开文件设备

引言 随着Android 10引入的Scoped Storage&#xff08;分区存储&#xff09;机制&#xff0c;传统的文件访问方式发生了重大变化。FFmpeg作为强大的多媒体处理工具&#xff0c;也在不断适应Android平台的演进。本文将介绍如何在FFmpeg 7.0版本中使用Android content协议直接访…

vue——v-pre的使用

&#x1f530; 基础理解 ✅ 什么是 v-pre&#xff1f; v-pre 是一个跳过编译的 Vue 指令。 它告诉 Vue&#xff1a;“这个元素和其子元素中的内容不要被编译处理&#xff0c;按原样输出。” ✅ 使用场景&#xff1a; 展示原始的 Mustache 插值语法&#xff08;{{ xxx }}&a…

PyTorch中TensorBoardX模块与torch.utils.tensorboard模块的对比分析

文章目录 说明1. 模块起源与开发背景2. 功能特性对比3. 安装与依赖关系4. 性能与使用体验5. 迁移与兼容性策略6. 最佳实践与建议7. 未来展望8. 结论实际相关信息推荐资源 说明 TensorBoard&#xff1a;独立工具&#xff0c;只需安装tensorboard。TensorFlow&#xff1a;非必需…

单片机中断系统工作原理及定时器中断应用

文件目录 main.c #include <REGX52.H> #include "TIMER0.H" #include "KEY.H" #include "DELAY.H"//void Timer0_Init() { // TMOD 0x01; // TL0 64536 % 256; // TH0 64536 / 256; // ET0 1; // EA 1; // TR0 1; //}unsigned char…

Python爬虫实战:研究Portia框架相关技术

1. 引言 1.1 研究背景与意义 在大数据时代,网络数据已成为企业决策、学术研究和社会分析的重要资源。据 Statista 统计,2025 年全球数据总量将达到 175ZB,其中 80% 以上来自非结构化网络内容。如何高效获取并结构化这些数据,成为数据科学领域的关键挑战。 传统爬虫开发需…

【机器学习基础】机器学习与深度学习概述 算法入门指南

机器学习与深度学习概述 算法入门指南 一、引言&#xff1a;机器学习与深度学习&#xff08;一&#xff09;定义与区别&#xff08;二&#xff09;发展历程&#xff08;三&#xff09;应用场景 二、机器学习基础&#xff08;一&#xff09;监督学习&#xff08;二&#xff09;无…

[C语言初阶]扫雷小游戏

目录 一、原理及问题分析二、代码实现2.1 分文件结构设计2.2 棋盘初始化与打印2.3 布置雷与排查雷2.4 游戏主流程实现 三、后期优化方向 在上一篇文章中&#xff0c;我们实现了我们的第二个游戏——三子棋小游戏。这次我们继续结合我们之前所学的所有内容&#xff0c;制作出我们…

ROS云课三分钟-破壁篇GCompris-一小部分支持Edu应用列表-2025

开启蓝桥云课ROS ROS 机器人操作系统初级教程_ROS - 蓝桥云课 安装和使用GCompris 终端输入&#xff1a;sudo apt install gcompris sudo apt install gcompris ok&#xff0c;完成即可。 sudo apt install gcompris 如果是平板&#xff0c;秒变儿童学习机。 启动 流畅运…

Linux系统基础——是什么、适用在哪里、如何选

一、Linux是什么 Linux最初是由林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;基于个人兴趣爱好开发的个人项目&#xff0c;他编写了最核心的内核&#xff1b;后面为了发展壮大Linux系统他将整个项目开源到GitHub上&#xff0c;可以让全世界的人都参与到项目的开发维护中…

26、AI 预测性维护 (燃气轮机轴承) - /安全与维护组件/ai-predictive-maintenance-turbine

76个工业组件库示例汇总 AI 预测性维护模拟组件 (燃气轮机轴承) 概述 这是一个交互式的 Web 组件,旨在模拟基于 AI 的预测性维护 (Predictive Maintenance, PdM) 概念,应用于工业燃气轮机的关键部件(例如轴承)。它通过模拟传感器数据、动态预测剩余使用寿命 (RUL),并根…

el-form 使用el-row el-col对齐 注意事项

1.el-form 使用inline&#xff0c;el-form-item宽度会失效。 2.为了保证el-form-item 和 它内部的el-input 能在一行&#xff0c;要设置el-form-item的label-width <el-form :model"editInspectform"><el-row style"margin-bottom: 20px"><…