天天看点

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;}" //鼠标触及滑块样式-滑块颜色
                                                      );
           

继续阅读