实现背景简介
在做QT项目时,遇到一个需求:QTableWidget(存在多行/列)拖拉至边界后,为了增强交互体验,增加回弹效果,用来提示没有更多内容。
在网络上面没有找到现成可参考的实现方法。
在这篇博客中 QListWidget 列表滑动回弹效果 介绍了一种QT自带的ScrollBar的滑动相关姿态实现,不过灵敏度太高,不知道怎么调节,同时由于我已经重写实现了了QTableWidget的触屏(或鼠标拖拽)滑动,触屏滑动后惯性减速功能等功能,于是决定在此基础之上继续实现回弹效果。
设计思路:
正在滑动时,在滑到最顶端或最低端时,且无更多内容时,根据当前所在位置是在行(列)首或行(列)尾,插入新的行(列),然后根据拖动距离调整新插入的行高(列宽),模拟有弹回效果。
释放后,如果不需要缓慢弹回效果,可以直接移除之前新增的行(列)。如果需要要缓慢弹回时,启动一个定时器以50ms间隔将释放时的行高(列宽)按指数级1/2逐渐拉回(每个定时间隔设定的宽或高上一次的一半),直至小于5,移除前面提到的新增的行(列)。
实现代码说明:
MyTableWidget.cpp中重写QTableWidget的鼠标事件,支持触屏滑动、边界回弹。应用时需要用MyTableWidget类提升QTableWidget
void mousePressEvent(QMouseEvent *ev)
void mouseMoveEvent(QMouseEvent *ev)
void mouseReleaseEvent(QMouseEvent *ev)
MyTableWidget.cpp实现
#include "mytablewidget.h"
#include <QDebug>
#include <QScrollBar>
#include <QScrollBar>
MyTableWidget::MyTableWidget(QWidget *parent) : QTableWidget(parent),
m_pressedAxis(0, 0),
m_curAdjustScrollBar( this->verticalScrollBar() ),
m_sliderDir(DIR_DEFAULT),
m_movedFlag(false),
m_pressedFlag(false),
m_initOneTimeFlag(false),
m_scrollBarVal(0),
m_preOffset(0),
m_adjustedCellNo(0),
m_preValSaved(0)
{
m_timer = new QTimer();
m_timer->stop();
connect(m_timer, &QTimer::timeout, this, &MyTableWidget::slotTimerOut);
}
MyTableWidget::~MyTableWidget()
{
}
void MyTableWidget::setSliderDir(ENUM_SLIDER_DIR dir)
{
m_sliderDir = dir;
// 区分横向或纵向,暂不同时支持横向纵向
if ( DIR_VERI == m_sliderDir )
{
m_curAdjustScrollBar = this->verticalScrollBar();
setWHFunPtr = &MyTableWidget::setRowHeight;
}
else
{
m_curAdjustScrollBar = this