效果
頭檔案:
#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;}" //滑鼠觸及滑塊樣式-滑塊顔色
);