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
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84399.shtml
英文地址,請注明出處:http://en.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"><…