天天看點

QtableView點選滑動設計

效果

QtableView點選滑動設計

頭檔案:

#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;}" //滑鼠觸及滑塊樣式-滑塊顔色
                                                      );
           

繼續閱讀