效果

头文件:
#ifndef CustomScroll_H
#define CustomScroll_H#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QTableView>
#include <QPropertyAnimation>
#include <QDateTime>class CustomScroll : public QWidget
{Q_OBJECT
#define SHOW_ROWS 10 //表格固定显示的行数
#define SCROL_WIDTH 10 //滚动条宽度
#define SCROL_CLOLOR QColor(150,150,150,140)
#define SCROL_SHOW_TIME 2000typedef 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;public:explicit CustomScroll(QTableView* table,QWidget *parent = NULL);public slots:void scrollTimeOut();
private:bool eventFilter(QObject *obj, QEvent *evt);QTimer m_scrollTimer; //用于控制右侧滚动条的显示QTableView *m_table; //构造函数传入的表格指针QScrollBar *m_scrollBar; //指向表格滚动条QPropertyAnimation *animation; //属性动画,使用动画驱动表格滑动int m_selectRow;int m_srcollH;
};#endif // CustomScroll_H
cpp文件
#include "customscroll.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),m_dragFlag(MOUSE_RELEASE)
{setAttribute(Qt::WA_TranslucentBackground);m_scrollBar = table->verticalScrollBar();m_scrollBar->hide();connect(m_scrollBar,&QScrollBar::sliderPressed,[=](){ m_scrollTimer.stop(); }); //按下滚动条connect(m_scrollBar,&QScrollBar::sliderMoved,[=](){ m_scrollTimer.stop(); });connect(m_scrollBar,&QScrollBar::sliderReleased,[=](){ m_scrollTimer.start(SCROL_SHOW_TIME); }); //松开滚动条animation = new QPropertyAnimation(m_scrollBar,"value",this); //创建动画对象connect(animation,&QPropertyAnimation::finished,[=](){ //动画结束后启动定时器准备隐藏滚动条m_scrollTimer.start(SCROL_SHOW_TIME);});connect(&m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollTimeOut()));m_table = table;m_table->viewport()->installEventFilter(this); //安装事件过滤器m_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);this->resize(SCROL_WIDTH,m_table->height());this->move(0,5); //将滑动条移至最右侧this->raise(); //置顶父窗口m_srcollH = m_table->height();
}void CustomScroll::scrollTimeOut()
{m_scrollBar->hide();m_dragFlag = MOUSE_RELEASE;
}bool CustomScroll::eventFilter(QObject *obj, QEvent *evt)
{static int pressPoint_y = 0; //记录按下位置static int dragPoint_y = -1; //拖动位置static qint64 pressMSec ; //记录按下的时间点int scrollV_max = m_scrollBar->maximum ();int scrollV_min = m_scrollBar->minimum ();QMouseEvent *mouse = dynamic_cast<QMouseEvent *>(evt);if(mouse){//=================== 按下 ===========================if( mouse->type() ==QEvent::MouseButtonPress){m_scrollTimer.stop();m_scrollBar->show();pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch(); //记录按下的时间dragPoint_y = mouse->pos().y(); //当前坐标pressPoint_y = dragPoint_y; //按下的位置animation->stop();m_selectRow = m_table->indexAt(mouse->pos()).row(); //选择当前行m_dragFlag = MOUSE_PRESS;}//======================= 只点击了一下屏幕,未移动 =============================else if(mouse->type() == QEvent::MouseButtonRelease && m_dragFlag == MOUSE_PRESS){m_dragFlag = MOUSE_RELEASE;m_scrollTimer.start(SCROL_SHOW_TIME); //2S后取消滑动条显示m_scrollBar->show();}//==================== 鼠标移动 ==============================else if((m_dragFlag!= MOUSE_RELEASE) && mouse->type() == QEvent::MouseMove){if(m_dragFlag == MOUSE_PRESS) //鼠标按下到现在的滑动状态,即表示首次滑动{if(qAbs(dragPoint_y - mouse->pos().y()) < 5) //判断移动阀值,避免误操作return true;else{m_dragFlag = MOUSE_PRESS_MOVE; //转为移动状态m_table->clearSelection(); //已经移动了,所以取消之前的选择dragPoint_y = mouse->pos().y(); //获取当前坐标return true;}}int moveValue = (dragPoint_y - mouse->pos().y()) + m_scrollBar->value(); //移动值 + 滚动条当前值 = 滑动到的位置dragPoint_y = mouse->pos().y();m_table->clearSelection();if(scrollV_min > moveValue) moveValue = scrollV_min; //添加位置限制if(moveValue > scrollV_max) moveValue = scrollV_max;m_scrollBar->setValue(moveValue); //表格显示到对应位置}//======================= 从按下滑动状态 到现在 鼠标松开,惯性滑动 =============================else if(m_dragFlag == MOUSE_PRESS_MOVE && mouse->type() == QEvent::MouseButtonRelease){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;return true;}else{int moveValue;if(ms > 1000) //滑动的时间不能超过1s{m_dragFlag = MOUSE_RELEASE;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;}m_table->clearSelection();//滑动松开后惯性滑动动画animation->setDuration(2000-ms);animation->setEndValue(moveValue);animation->setEasingCurve(QEasingCurve::OutQuart);animation->start();m_dragFlag = MOUSE_RELEASE_MOVE; //鼠标松开,惯性滑动状态}}}return QWidget::eventFilter(obj,evt);
}
使用方法
CustomScroll *tableMove;tableMove = new CustomScroll(ui->tableView,this);
qtableView初始化建议
ui->tableView->verticalHeader()->setVisible(false); //隐藏序号列ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); //设置点击选择方式,行、列、单元格ui->tableView->setSelectionMode(QAbstractItemView::MultiSelection); //设置可选择条目数ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); //内容不可编辑ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); //设置表头不可拖动ui->tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //去掉水平滚动条//ui->tableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //去掉垂直滚动条
建议滚动条样式
//设置纵向滚动条样式ui->tableView->verticalScrollBar()->setStyleSheet("QScrollBar{""background:white;"//背景色"width:20px;""QScrollBar::sub-line{background:transparent;}" //向上箭头样式"QScrollBar::add-line{background:transparent;}" //向下箭头样式"}""QScrollBar::handle{" //滑块样式"background:#d0d0d0; ""border:2px solid transparent;""border-radius:10px;""hover{background:#d0d0d0;}""}""QScrollBar::handle:vertical:hover{background:#a0a0a0;}" //鼠标触及滑块样式-滑块颜色);
















