【Qt】实现模拟触摸屏 上下滑动表格 的两种方式

news/2024/9/22 15:37:45/

QScroller

Qt QTableWidget 触摸屏上滑动效果

代码

    // 创建 QScroller 对象并与 tableWidget 关联.QScroller *pScroller = QScroller::scroller(ui->tableView);// 捕获滚动手势.pScroller->grabGesture(ui->tableView, QScroller::LeftMouseButtonGesture);// 设置垂直滚动模式为逐像素滚动.ui->tableView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);

不足

自带的滚动条失效
:右侧拖动滚动条滑动,反而触发了触摸滑动操作
还未解决请添加图片描述

自定义 CustomScroll

源自:Qt利用tablewidget模拟手指实现滑动

效果

请添加图片描述

代码

CustomScrollWidget.h

#ifndef CUSTOMSCROLLWIDGET_H
#define CUSTOMSCROLLWIDGET_H#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QTableView>
#include <QPropertyAnimation>
#include <QDateTime>
class CustomScroll : public QWidget
{Q_OBJECTtypedef enum tagLuiScrollMouseDragInfo {MOUSE_RELEASE = 0,                       //鼠标离开MOUSE_PRESS = 1,                         //按下MOUSE_PRESS_MOVE = 2,                   //按下移动MOUSE_RELEASE_MOVE = 3                   //鼠标离开并滑动}LUI_Scroll_Mouse_Drag_INFO_E;LUI_Scroll_Mouse_Drag_INFO_E m_dragFlag = MOUSE_RELEASE;QTimer m_scrollTimer;QTimer m_selectTimer;QTableView *m_table;QScrollBar *m_scrollBar;QPropertyAnimation *animation;int  m_selectRow;int  m_srcollH;void paintEvent(QPaintEvent *);bool eventFilter(QObject *obj, QEvent *evt);public:explicit CustomScroll(QTableView* table,QWidget *parent = nullptr);signals:public slots:void scrollTimeOut();void selectTimeOut();
};#endif // CUSTOMSCROLLWIDGET_H

CustomScrollWidget.cpp

#include "CustomScrollWidget.h"
#include <QMouseEvent>
#include <QDebug>
#include <QApplication>
#include <QPainter>
#include <QTableWidget>
#include <QHeaderView>
#include <QScrollBar>
#include <QAbstractAnimation>CustomScroll::CustomScroll(QTableView* table,QWidget *parent) : QWidget(parent)
{
#define  SRCOLL_HEIGHT  22setAttribute(Qt::WA_TranslucentBackground);m_table = table;m_scrollBar = table->verticalScrollBar();m_table->viewport()->installEventFilter(this);m_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);animation =  new QPropertyAnimation(m_scrollBar,"value",this);connect(&m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollTimeOut()));connect(&m_selectTimer,SIGNAL(timeout()),this,SLOT(selectTimeOut()));this->setMinimumSize(10, table->height());this->setMaximumSize(10, table->height());this->move(table->width()-10,0);            //将滑动条移至最右侧this->raise();m_srcollH  = table->height()* SRCOLL_HEIGHT/100.0;
}void CustomScroll::selectTimeOut()
{m_table->selectRow(m_selectRow);m_selectTimer.stop();this->update();
}void CustomScroll::scrollTimeOut()
{if(m_dragFlag == MOUSE_RELEASE_MOVE && animation->state()==QAbstractAnimation::Stopped) //停下来了{this->update();m_dragFlag = MOUSE_RELEASE;m_scrollTimer.setInterval(1000);}else{this->update();if(m_scrollTimer.interval()==1000)m_scrollTimer.stop();}}bool CustomScroll::eventFilter(QObject *obj, QEvent *evt)
{static int pressPoint_y   = 0;static int dragPoint_y    = -1;static qint64 pressMSec ;QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);int scrollV_max = m_scrollBar->maximum ();int scrollV_min = m_scrollBar->minimum ();//根据鼠标的动作——按下、放开、拖动,执行相应的操作if(mouse){if( mouse->type() ==QEvent::MouseButtonPress)    //首次按下{pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch();     //记录按下的时间dragPoint_y  = mouse->pos().y();               //当前坐标pressPoint_y = dragPoint_y;                      //按下的位置animation->stop();m_selectRow =  m_table->indexAt(mouse->pos() ).row();    //选择当前行qDebug()<<mouse->pos()<<m_selectRow;m_selectTimer.start(100);m_dragFlag = MOUSE_PRESS;return true;}else if(mouse->type() == QEvent::MouseButtonRelease && m_dragFlag == MOUSE_PRESS)   //未移动{m_dragFlag = MOUSE_RELEASE;if(!m_scrollTimer.isActive())m_scrollTimer.start(1000);  //1S后取消滑动条显示return true;}else if(mouse->type() == QEvent::MouseButtonRelease && m_dragFlag == MOUSE_PRESS_MOVE){dragPoint_y = -1;int releasePoint_y = mouse->pos().y();int ms= QDateTime::currentDateTime().toMSecsSinceEpoch()-pressMSec;int Pixel_per_second=qAbs(releasePoint_y - pressPoint_y)*1000/ms;       //计算每秒像素点if(Pixel_per_second<300 || qAbs(releasePoint_y - pressPoint_y) < 45){m_dragFlag = MOUSE_RELEASE;if(!m_scrollTimer.isActive())m_scrollTimer.start(1000);  //1S后取消滑动条显示return true;}else{int moveValue ;if(ms > 1000)      //滑动的时间太长{m_dragFlag = MOUSE_RELEASE;if(!m_scrollTimer.isActive())m_scrollTimer.start(1000);  //1S后取消滑动条显示return true;}if(releasePoint_y - pressPoint_y > 0)     //向下滑动{moveValue = m_scrollBar->value() - Pixel_per_second*0.2*(300/ms);//滑动时间越长,moveValue值越小,因为不是快速滑动if(moveValue < scrollV_min){moveValue = scrollV_min;}}else{moveValue = m_scrollBar->value() + Pixel_per_second*0.2*(300/ms);if(moveValue > scrollV_max){moveValue = scrollV_max;}}animation->setDuration(2000-ms);animation->setEndValue(moveValue);animation->setEasingCurve(QEasingCurve::OutQuart);if(!m_scrollTimer.isActive())m_scrollTimer.start(50);  //定时刷新滑动条显示animation->start();m_dragFlag = MOUSE_RELEASE_MOVE;}return true;}else if(mouse->type() == QEvent::MouseMove && (m_dragFlag!= MOUSE_RELEASE) ){if(  m_dragFlag == MOUSE_PRESS)     //开始移动{if(qAbs(dragPoint_y - mouse->pos().y()) < 4)      //判断移动阀值,避免误操作return true;else{m_dragFlag = MOUSE_PRESS_MOVE;if(m_selectTimer.isActive())                         //已经移动了,所以取消选择m_selectTimer.stop();m_table->clearSelection();dragPoint_y = mouse->pos().y();                      //获取当前坐标update();return true;}}int moveValue = ( dragPoint_y-mouse->pos().y())+m_scrollBar->value();    //差距dragPoint_y = mouse->pos().y();                        //获取当前坐标if(scrollV_min > moveValue){moveValue = scrollV_min;}if(moveValue > scrollV_max){moveValue = scrollV_max;}m_scrollBar->setValue(moveValue);update();return true;}}return QWidget::eventFilter(obj,evt);
}void CustomScroll::paintEvent(QPaintEvent *)
{
#define  WIDTH 6  //滑动条的宽度.
#define  MIN_HEIGHT 26if(m_dragFlag== MOUSE_RELEASE||m_dragFlag== MOUSE_PRESS){return;}int scrollV_max = m_scrollBar->maximum ();QPainter painter(this);int y = (m_table->verticalScrollBar()->value()*(m_table->height()-m_srcollH))/(float)(scrollV_max);painter.setPen(Qt::NoPen);// painter.setBrush(QColor(180,180,180,200));// painter.drawRoundedRect(0,0,this->width(),this->height(),3,3);painter.setBrush(QColor(80,80,80,140));painter.drawRoundedRect(0,y,WIDTH,m_srcollH,3,3);
}

Form.h

使用:创建界面,创建tableView对象,作为参数创建CustomScroll ,经过处理,tableView对象再添加进界面显示交互。


#ifndef FORM_H
#define FORM_H#include <QWidget>
#include <QStandardItemModel>
namespace Ui {
class Form;
}class Form : public QWidget
{Q_OBJECTpublic:explicit Form(QWidget *parent = nullptr);~Form();private:Ui::Form *ui;
};#endif // FORM_H

Form.cpp

#include "form.h"
#include "ui_form.h"
#include <QTableView>
#include <QHeaderView>
#include "CustomScrollWidget.h"
Form::Form(QWidget *parent): QWidget(parent), ui(new Ui::Form)
{ui->setupUi(this);// 创建一个简单的表格视图QTableView *tableView = new QTableView;QStandardItemModel *model = new QStandardItemModel(/*100, 5*/); // 100 行,5 列for (int var = 0; var < 100; ++var) {QList<QStandardItem*>items;items<<new QStandardItem("111")<<new QStandardItem("222")<<new QStandardItem("333")<<new QStandardItem("444");model->appendRow(items);}tableView->setModel(model);// 创建自定义滚动条CustomScroll *customScroll = new CustomScroll(tableView);ui->verticalLayout->addWidget(tableView);}Form::~Form()
{delete ui;
}

http://www.ppmy.cn/news/1528884.html

相关文章

javascript数据结构

在 JavaScript 中&#xff0c;数据结构的选择和实现对于编写高效、可维护的代码至关重要。JavaScript 提供了一系列内置的数据结构&#xff0c;同时也支持自定义复杂的数据结构。以下是 JavaScript 中常用的一些数据结构及其基本介绍&#xff1a; 内置数据结构 1. 数组&#…

JavaScript发送邮件:实现前端触发的教程?

JavaScript发送邮件的方式&#xff1f;怎么使用JavaScript发信&#xff1f; 无论是用户反馈、联系表单还是自动通知&#xff0c;前端触发的邮件发送功能都能极大地提升用户体验。AokSend将详细介绍如何通过JavaScript发送邮件&#xff0c;实现前端触发的邮件发送功能。 JavaS…

Unity 百度AI实现无绿幕拍照抠像功能(详解版)

目录 一、前言 1.抠像效果 2.去哪找百度ai抠图 3.基础流程跳过 二、获取AccessToken 1.什么是Token 2.为什么要获取Token 3.如何获取token 4.解析json 5.完整代码 三、抠像 1.准备地址 2.建立链接&#xff0c;和基本配置 3.图片格式转换 4.开始上传 5.获取回复…

IPsec-Vpn

网络括谱图 IPSec-VPN 配置思路 1 配置IP地址 FWA:IP地址的配置 [FW1000-A]interface GigabitEthernet 1/0/0 [FW1000-A-GigabitEthernet1/0/0]ip address 10.1.1.1 24 [FW1000-A]interface GigabitEthernet 1/0/2 [FW1000-A-GigabitEthernet1/0/2]ip address

No operations allowed after statement closed

错误信息&#xff1a; The last packet successfully received from the server was 3,576,246 milliseconds ago. The last packet sent successfully to the server was 3,576,247 milliseconds ago. 参考解决方案 https://github.com/alibaba/druid/issues/5549 如果修改…

【网络安全】分享4个高危业务逻辑漏洞

未经许可,不得转载。 文章目录 正文逻辑漏洞1逻辑漏洞2逻辑漏洞3逻辑漏洞4其它正文 该目标程序是一家提供浏览器服务的公司,其核心功能是网页抓取和多账户登录操作,类似于浏览器中的隐身模式,但更加强大和高效。通过该平台,用户可以轻松管理并同时运行数百个隐身浏览器实…

关机整蛊游戏

目录 目标 实现关机 取消关机 system()函数 strcmp()函数 实现代码 伪装 目标 让你的朋友输入指定信息&#xff0c;否则电脑关机。 实现关机 在电脑的命令提示符中&#xff0c;如果输入&#xff1a; shutdown -s -t 60 则代表在60s后电脑将关机。 取消关机 在电脑…

C# 委托与事件 观察者模式

委托与事件是一种观察者模式。 什么是委托与事件 在c#中&#xff0c;委托类似于代理&#xff0c;也跟其它语言的函数指针、回调函数等相似&#xff0c;但委托是类型安全和可靠的。声明自定义委托时&#xff0c;加上delegate关键字&#xff0c;委托定义类似于接口。 事件是特殊…