源文件:
#include “smoothscrollbar.h”
#include
SmoothScrollBar::SmoothScrollBar(QWidget* parent):QScrollBar(parent)
{
m_scrollAni=new QPropertyAnimation;
m_scrollAni->setTargetObject(this);
m_scrollAni->setPropertyName(“value”);
m_scrollAni->setEasingCurve(QEasingCurve::OutQuint); //设置动画曲线,在Qt文档中有详细的介绍
m_scrollAni->setDuration(800); //设置动画时间,数值越小播放越快
m_targetValue_v=value(); //将m_targetValue_v初始化
}
void SmoothScrollBar::setValue(int value)
{
m_scrollAni->stop();//停止现在的动画,防止出现冲突
m_scrollAni->setStartValue(this->value()); //设置动画滚动的初始值为当前位置
m_scrollAni->setEndValue(value); //设置动画的结束位置为目标值
m_scrollAni->start(); //开始动画
}
void SmoothScrollBar::scroll(int value)
{
m_targetValue_v-=value; //将目标值和相对位置进行运算
setValue(m_targetValue_v); //开始动画
}
void SmoothScrollBar::mousePressEvent(QMouseEvent *e)
{
//当使用鼠标操作滚动条时,不会刷新m_targetValue_v的值,因而需要重写事件,对其进行刷新。
m_scrollAni->stop();
QScrollBar::mousePressEvent(e);
m_targetValue_v=value();
}
void SmoothScrollBar::mouseReleaseEvent(QMouseEvent *e)
{
m_scrollAni->stop();
QScrollBar::mouseReleaseEvent(e);
m_targetValue_v=value();
}
void SmoothScrollBar::mouseMoveEvent(QMouseEvent *e)
{
m_scrollAni->stop();
QScrollBar::mouseMoveEvent(e);
m_targetValue_v=value();
}
二、自定义列表控件
将列表的滚动条替换为我们刚刚自定义的滚动条
头文件:
#ifndef SMOOTHSCROLLAREA_H
#define SMOOTHSCROLLAREA_H
#include
#include
#include “smoothscrollbar.h”
class SmoothScrollArea : public QScrollArea
{
Q_OBJECT
public:
explicit SmoothScrollArea(QWidget *parent = nullptr);
private:
SmoothScrollBar* vScrollBar; //纵向滚动条
void wheelEvent(QWheelEvent* e); //捕获鼠标滚轮事件
};
#endif // SMOOTHSCROLLAREA_H
源文件:
#include “smoothScrollArea.h”
#include
#include
#include
#include
SmoothScrollArea::SmoothScrollArea(QWidget *parent) : QScrollArea(parent)
{
auto layout = new QVBoxLayout;
vScrollBar=new SmoothScrollBar();
vScrollBar->setOrientation(Qt::Orientation::Vertical); //将滚动条设置为纵向
QWidget* w=new QWidget; //主体Widget
for (int i=0;i<200 ;i++ ) { //在w中加入200个label,用来测试滚动
QFont font;
font.setPointSize(i+1);
auto a=new QLabel(QString::number(i));
a->setFont(font);
layout->addWidget(a);
}
setVerticalScrollBar(vScrollBar); //设置纵向滚动条
w->setLayout(layout); //设置布局
setWidget(w); //设置widget
}
void SmoothScrollArea::wheelEvent(QWheelEvent *e)
{
//当捕获到事件后,调用相对滚动的槽函数
vScrollBar->scroll(e->angleDelta().y());
}
到此为止,SmoothScrollArea
类便可以支持纵向的平滑滚动。其他的列表控件方法一致。
三、测试效果
将SmoothScrollArea
列表控件加入到主窗口后,运行即可。
补充
–
在此之前参考过deepin-launcher
的小窗口模式列表代码,deepin的平滑滚动策略存在缺陷,导致体验较差。这里我详细说明一下这一简单的问题,非deepin用户或开发者可以到此为止了。
/**
-
@brief AppListView::wheelEvent 鼠标滑轮事件触发滑动区域控件动画
-
@param e 鼠标滑轮事件指针对象
*/
void AppListView::wheelEvent(QWheelEvent *e)
{
if (e->orientation() == Qt::Horizontal)
return;
int offset = -e->delta();
m_scrollAni->stop();
m_scrollAni->setStartValue(verticalScrollBar()->value());
m_scrollAni->setEndValue(verticalScrollBar()->value() + offset * m_speedTime);
m_scrollAni->start();
}
由代码中可以看到,首先他屏蔽了横向滑动的事件,这个主要应对触控板的一些问题。
offset
为滚动的距离,每次滚动之前先停止上次动画(如果还没有结束的话),然后在以当前位置为起始位置,以相对offset的位置为结束位置,这就会导致一个问题。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
)]
[外链图片转存中…(img-lJDQzXjn-1715876677933)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!