效果
头文件:
#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 2000
typedef 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;}" //鼠标触及滑块样式-滑块颜色
);