qstyle 一步一个jio印(3)—— 添加动画 水波纹效果

13 篇文章 0 订阅
9 篇文章 0 订阅

添砖加瓦

细想已经实现了一个控件的各种状态(聚焦、鼠标悬浮、点击、使能、失能等)中的样式绘制和控制,已经基本上完成了定制的实现了,剩下就是能够为这个控件加点什么,比如说,加个水波纹动画啥的。

看看源码中的动画实现,那才叫真正的框架啊啊啊,真正的框架是看不懂的额。

所以说,只能尽量理解源码中的方法,加上查阅一下资料,再一行一行慢慢验证实验看下了。

这次我们就不追求别人的框架了,先用最浅显的代码弄好效果再说吧qaq。

动画

通过查看相关资料,说白了qt动画最必要的是在一段短时间内生成一堆连续的间隔较小的数,如透明度,当透明度为1时就是不透明,为0就是全透明,在0 - 1之间生成间隔不大的很多个数,再应用在控件上,就有了渐渐不透明或者渐渐透明的动画效果~

这次的目标,水波纹包含着两个数,一个是画水波纹不断扩大的圆型,另一个就是让水波纹逐渐消失透明度。

在那些绘制函数里,有控件的画笔,直接用这只笔基于这个控件再画一层东西即可。

而数据产生,qt有类QParallelAnimationGroup、QPropertyAnimation帮我们解决,QPropertyAnimation用法通常为绑定某控件的属性,设置开始数值和结束数和时间,产生一堆两数值间的一堆数据应用在这个控件的属性上,对这个属性进行改动。

而目标是再画一层水波纹,不方便直接修改控件的属性,所以新建一个数据类保存这些数据,让QPropertyAnimation绑定的是这个类的属性即可。

动手

学习下源码,在代码目录下新建一个animation的类,里面存放所有关于动画的实现文件。

我们目标很明确,随便弄个类,里面有两个变量方便绑定即可。

新建类绑定变量

新建一个类,继承QParallelAnimationGroup,类里面加入方便绑属性

Q_PROPERTY(qreal radius WRITE setRadius READ radius)
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)

新建属性:

QPropertyAnimation *const m_radiusAnimation;
QPropertyAnimation *const m_opacityAnimation;
QWidget            *const m_target;
qreal                     m_radius;
qreal                     m_opacity;

其中QPropertyAnimation就是能产生一堆连续数据的类了,target用来绑定控件。

绑定的代码如下:

QPropertyAnimation *m_opacityAnimation = new QPropertyAnimation;
m_opacityAnimation->setTargetObject(this);
m_opacityAnimation->setPropertyName(“opacity”);
m_opacityAnimation->setEasingCurve(easing);
m_opacityAnimation->setDuration(duration);
addAnimation(animation);

首先把setTargetObject,目标为这个类,setPropertyName也就绑定了这个类的opacity属性,也是刚刚新建的Q_PROPERTY里面。再添加开始数值,结束数值,时间,就可以等待它的start了:

m_opacityAnimation->setStartValue(1);
m_opacityAnimation->setEndValue(0);
m_opacityAnimation->setDuration(duration);

由于是改动了Q_PROPERTY里的数值,自定义一下设置这个数值的函数:

void MaterialRipple::setOpacity(qreal opacity)
{
    if (qFuzzyCompare(m_opacity,opacity)) {
        return;
    }
    m_opacity = opacity;
    m_target->update();
}

这个target就是我们待绘制的button,调用它的update时它会进行一次绘制,相当于通知了这个button要进行绘制了,我的opacity更新了。

radius也是一模一样的,改一下数值即可;

button触发

就是点击的时候触发了这个水波纹动画,在mystyle中是removeEventFilter了button和重新installEventFilter了一遍的,所以写eventfilter时加入:

{% btn 'https://nightcivet.site/qstyle-3/',qstyle 一步一个jio印(3)—— 添加动画 水波纹效果,far fa-hand-point-right,outline blue larger %}bool MyStyle::eventFilter(QObject *object, QEvent *event)
{
    if (QPushButton *button = qobject_cast<QPushButton *>(object)) {
        switch (event->type()) {
            case QEvent::MouseButtonPress:
            {
				xxx...
            }
        }
    }

    return QCommonStyle::eventFilter(object, event);
}

这里的内容xxx即可上刚刚新建的类,同时可以把button参数传进去了!调用动画类的start(),就开始了数据产生!

画!

直接在drawPanelButtonCommandPrimitive函数最后加入:

if (ripple && enabled){
        const QPointF center = ripple->center();
        painter->setOpacity(ripple->opacity());
        QBrush brush;
        brush.setColor(palette.color(QPalette::Highlight));
        brush.setStyle(Qt::SolidPattern);
        painter->setBrush(brush);
        painter->drawEllipse(center, ripple->radius(), ripple->radius());
}

这个ripple便是新建的数据类,表示波纹嘛,和之前说的一样,设置透明度,画圆即可。

效果!

故意调慢了一点时间,颜色也随便上了,就是这样的效果。

bug还是挺多的,比如连续点击时会出问题,两个button快速切换点击也是,其实就是没有处理动画还没完成的情况,包括控件多的时候的情况;

就是缺乏对这种数据的管理,所以源码框架就是做这些事情,管理控件与动画的绑定,管理动画开始结束的控制。
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值