1、概述
源码放在文章末尾
该项目实现动画按钮,鼠标放在按钮上可以弹性拉出的三个按钮,使用贝塞尔曲线实现,项目demo显示如下所示:
项目部分代码如下所示:
#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
#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;
}