《QT实用小工具·五十四》果冻弹出效果的动画按钮

1、概述
源码放在文章末尾

该项目实现动画按钮,鼠标放在按钮上可以弹性拉出的三个按钮,使用贝塞尔曲线实现,项目demo显示如下所示:

项目部分代码如下所示:

cpp 复制代码
#ifndef WATERCIRCLEBUTTON_H
#define WATERCIRCLEBUTTON_H

#include <QObject>
#include <QWidget>
#include "interactivebuttonbase.h"

class WaterCircleButton : public InteractiveButtonBase
{
public:
    WaterCircleButton(QWidget* parent = nullptr);
    WaterCircleButton(QIcon icon, QWidget* parent = nullptr);
    WaterCircleButton(QPixmap pixmap, QWidget* parent = nullptr);

protected:
    void enterEvent(QEvent* event) override;
    void leaveEvent(QEvent* event) override;
    void mousePressEvent(QMouseEvent* event) override;
    void mouseReleaseEvent(QMouseEvent* event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;

    QPainterPath getBgPainterPath() override;
    QPainterPath getWaterPainterPath(Water water) override;

    void simulateStatePress(bool s = true);
    bool inArea(QPoint point) override;

protected:
    QPoint center_pos;
    bool in_circle;
    int radius;
};

#endif // WATERCIRCLEBUTTON_H
cpp 复制代码
#include "watercirclebutton.h"

WaterCircleButton::WaterCircleButton(QWidget* parent) : InteractiveButtonBase (parent), in_circle(false), radius(16)
{

}

WaterCircleButton::WaterCircleButton(QIcon icon, QWidget *parent) : InteractiveButtonBase (icon, parent), in_circle(false), radius(16)
{

}

WaterCircleButton::WaterCircleButton(QPixmap pixmap, QWidget *parent) : InteractiveButtonBase (pixmap, parent), in_circle(false), radius(16)
{

}

void WaterCircleButton::enterEvent(QEvent *event)
{

}

void WaterCircleButton::leaveEvent(QEvent *event)
{
    if (in_circle && !pressing && !inArea(mapFromGlobal(QCursor::pos())))
    {
        in_circle = false;
        InteractiveButtonBase::leaveEvent(event);
    }
}

void WaterCircleButton::mousePressEvent(QMouseEvent *event)
{
    if (in_circle || (!hovering && inArea(event->pos())))
        return InteractiveButtonBase::mousePressEvent(event);
}

void WaterCircleButton::mouseReleaseEvent(QMouseEvent *event)
{
    if (pressing)
    {
        InteractiveButtonBase::mouseReleaseEvent(event);

        if (leave_after_clicked || (!inArea(event->pos()) && !pressing)) // 鼠标移出
        {
            in_circle = false;
            InteractiveButtonBase::leaveEvent(nullptr);
        }
    }
}

void WaterCircleButton::mouseMoveEvent(QMouseEvent *event)
{
    bool is_in = inArea(event->pos());

    if (is_in && !in_circle)// 鼠标移入
    {
        in_circle = true;
        InteractiveButtonBase::enterEvent(nullptr);
    }
    else if (!is_in && in_circle && !pressing) // 鼠标移出
    {
        in_circle = false;
        InteractiveButtonBase::leaveEvent(nullptr);
    }

    if (in_circle)
        InteractiveButtonBase::mouseMoveEvent(event);
}

void WaterCircleButton::resizeEvent(QResizeEvent *event)
{
    center_pos = geometry().center() - geometry().topLeft();
    radius = min(size().width(), size().height())/ 2;

    return InteractiveButtonBase::resizeEvent(event);
}

QPainterPath WaterCircleButton::getBgPainterPath()
{
    QPainterPath path;
    int w = size().width(), h = size().height();
    QRect rect(w/2-radius, h/2-radius, radius*2, radius*2);
    path.addEllipse(rect);
    return path;
}

QPainterPath WaterCircleButton::getWaterPainterPath(InteractiveButtonBase::Water water)
{
    QPainterPath path = InteractiveButtonBase::getWaterPainterPath(water) & getBgPainterPath();
    return path;
}

void WaterCircleButton::simulateStatePress(bool s)
{
    in_circle = true;
    InteractiveButtonBase::simulateStatePress(s);
    in_circle = false;
}

bool WaterCircleButton::inArea(QPoint point)
{
    return (point - center_pos).manhattanLength() <= radius;
}

源码下载

相关推荐
Chase_______几秒前
【Java杂项】为什么 long 可以自动转 float?宽化基本类型转换与精度丢失详解
java·开发语言·python
listhi5201 分钟前
基于QT的串口心电波形实时显示系统
开发语言·qt
之歆2 分钟前
DAY_12JavaScript DOM 完全指南(三):高级工程篇
开发语言·前端·javascript·ecmascript
invicinble2 分钟前
java数组相关的信息量
java·开发语言·python
码小猿的CPP工坊3 分钟前
AI时代C++软件开发工程师的思考
c++·人工智能
牧瀬クリスだ7 分钟前
Java线程——从创建第一个线程到休眠线程
java·开发语言
蜡笔小马10 分钟前
13.C++设计模式-策略模式
c++·设计模式·策略模式
我命由我1234512 分钟前
Android 开发问题:TextView 内容超过宽度时,默认不会换行
android·开发语言·java-ee·android studio·android jetpack·android-studio·android runtime
计算机安禾13 分钟前
【c++面向对象编程】第36篇:析构函数应永远不抛出异常——原因与最佳实践
开发语言·c++
一条泥憨鱼17 分钟前
【Java 进阶】LinkedHashMap 与 TreeMap
java·开发语言·数据结构·笔记·后端·学习