当前位置: 首页 > news >正文

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.xdnf.cn/news/563941.html

相关文章:

  • AI赋能R-Meta分析核心技术:从热点挖掘到高级模型
  • 【音频】wav文件如何解析编码格式(压缩格式)?
  • 前端开发遇到 Bug,怎么办?如何利用 AI 高效解决问题
  • 电脑中所有word文件图标变白怎么恢复
  • WebSocket 是什么?
  • SQL 数值计算全解析:ABS、CEIL、FLOOR与ROUND函数深度精讲
  • 深入了解redis的哈希槽的知识
  • 关于收集 Android Telephony 网络信息的设计思考
  • 网络基础的介绍
  • 如何提高独立服务器的安全性?
  • 从电商角度设计大模型的 Prompt
  • Java 参数值传递机制
  • 全平台开源电子书阅读器推荐,支持多端同步+AI朗读!支持epub/mobi/azw3/pdf常见电子书格式!
  • PostgreSQL基础操作
  • 29.第二阶段x64游戏实战-技能冷却
  • Node.js 24发布:性能与安全双提升
  • 【Vue篇】重剑无锋:面经PC项目工程化实战面经全解
  • 苹果企业签名为什么会出现授信异常
  • 《从虚拟 DOM 到 Diff 算法:深度解析前端高效更新的核心原理》-简版
  • logits是啥、傅里叶变换
  • day 32
  • 谷歌I/O 2025 完全指南:由Gemini开创的AI新时代及其对我们未来的影响
  • DevExpress Blazor中文教程 - 如何用AI聊天组件构建大型语言模型聊天APP?
  • vscode连接本地Ubuntu
  • OBOO鸥柏丨AI数字人触摸屏查询触控人脸识别语音交互一体机上市
  • SpringCloud(二)
  • Unity-编辑器扩展-其二
  • 电子电气架构 --- 细化造车阶段流程
  • 第一性原理(First Principles Thinking)——颠覆性创新的底层逻辑
  • LM-BFF——语言模型微调新范式