代码:
#ifndef COLORGRADIENTROUNDEDBUTTON_H
#define COLORGRADIENTROUNDEDBUTTON_H
#include <QAbstractButton>
struct doubleColor
{
doubleColor(QColor frist = Qt::red,QColor second = Qt::blue)
:fristColor(frist),secondColor(second)
{}
QColor fristColor;
QColor secondColor;
bool operator !=(const doubleColor & c)
{
return (this->fristColor != c.fristColor) || (this->secondColor != c.secondColor);
}
};
Q_DECLARE_METATYPE(doubleColor)
class ColorGradientRoundedButton : public QAbstractButton
{
Q_OBJECT
Q_PROPERTY(doubleColor currentColor MEMBER currentColor)
public:
ColorGradientRoundedButton(QWidget *parent = nullptr);
~ColorGradientRoundedButton()override;
protected:
void paintEvent(QPaintEvent *event)override;
void enterEvent(QEnterEvent *event)override;
void leaveEvent(QEvent *event)override;
private:
void onValueChanged(const QVariant &value);
doubleColor currentColor;
doubleColor startColor;
doubleColor endColor;
class QPropertyAnimation * animation{nullptr};
};
#endif // COLORGRADIENTROUNDEDBUTTON_H
#include "colorgradientroundedbutton.h"
#include <QPainter>
#include <QPaintEvent>
#include <QGraphicsDropShadowEffect>
#include <QPropertyAnimation>
#include <QDebug>
#include <QPainterPath>
#include <QRandomGenerator>
QVariant myColorInterpolator(const doubleColor &start, const doubleColor &end, qreal progress)
{
auto fr = start.fristColor.red() + ((end.fristColor.red() - start.fristColor.red()) * progress);
auto fg = start.fristColor.green() + ((end.fristColor.green() - start.fristColor.green()) * progress);
auto fb = start.fristColor.blue() + ((end.fristColor.blue() - start.fristColor.blue()) * progress);
auto sr = start.secondColor.red() + ((end.secondColor.red() - start.secondColor.red()) * progress);
auto sg = start.secondColor.green() + ((end.secondColor.green() - start.secondColor.green()) * progress);
auto sb = start.secondColor.blue() + ((end.secondColor.blue() - start.secondColor.blue()) * progress);
return QVariant::fromValue(doubleColor(QColor(fr,fg,fb),QColor(sr,sg,sb)));
}
QColor getRandomColor()
{
return QColor(QRandomGenerator::global()->bounded(255),
QRandomGenerator::global()->bounded(255),
QRandomGenerator::global()->bounded(255));
}
ColorGradientRoundedButton::ColorGradientRoundedButton(QWidget *parent)
: QAbstractButton(parent)
{
qRegisterAnimationInterpolator<doubleColor>(myColorInterpolator);
startColor = doubleColor(getRandomColor(),getRandomColor());
endColor = doubleColor(getRandomColor(),getRandomColor());
currentColor = startColor;
this->setMinimumSize(180,50);
setMouseTracking(true);
QGraphicsDropShadowEffect * effect = new QGraphicsDropShadowEffect(this);
setGraphicsEffect(effect);
effect->setOffset(0,0);
effect->setBlurRadius(25);
effect->setColor(Qt::black);
animation = new QPropertyAnimation(this, "currentColor");
animation->setDuration(400);
connect(animation,&QPropertyAnimation::valueChanged,this,&ColorGradientRoundedButton::onValueChanged);
}
ColorGradientRoundedButton::~ColorGradientRoundedButton()
{
}
void ColorGradientRoundedButton::onValueChanged(const QVariant &value)
{
update();
}
void ColorGradientRoundedButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
auto rect = event->rect();
QPainterPath path;
path.addRoundedRect(rect,25,25);
painter.setClipPath(path);
painter.drawRect(rect);
QLinearGradient linearGradient(rect.topLeft(),rect.topRight());
linearGradient.setColorAt(0,currentColor.fristColor);
linearGradient.setColorAt(1,currentColor.secondColor);
painter.fillRect(rect,linearGradient);
auto font = painter.font();
font.setBold(true);
font.setPixelSize(20);
painter.setFont(font);
painter.setPen(Qt::white);
painter.drawText(rect,Qt::AlignCenter,text());
}
void ColorGradientRoundedButton::enterEvent(QEnterEvent *event)
{
if(animation->state() == QAbstractAnimation::Running)
{
animation->stop();
}
animation->setStartValue(QVariant::fromValue(currentColor));
animation->setEndValue(QVariant::fromValue(endColor));
animation->start();
QWidget::enterEvent(event);
}
void ColorGradientRoundedButton::leaveEvent(QEvent *event)
{
if(animation->state() == QAbstractAnimation::Running)
{
animation->stop();
}
animation->setStartValue(QVariant::fromValue(currentColor));
animation->setEndValue(QVariant::fromValue(startColor));
animation->start();
QWidget::leaveEvent(event);
}
使用示例:
QWidget w;
w.setPalette(Qt::white);
auto vb = new QVBoxLayout;
vb->setSpacing(15);
for(int i = 0;i < 8;++i)
{
auto btn = new ColorGradientRoundedButton;
btn->setText(QString("按钮%1").arg(i));
vb->addWidget(btn);
}
w.setLayout(vb);
w.show();
效果: