Qt编写自定义控件:彩色渐变圆角按钮之一

代码:

#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();

效果:

相关博文:Qt动画框架:QVariantAnimation

Qt/C++是一种开发桌面应用程序的跨平台开发框架,它提供了丰富的工具和类库,能够方便快捷地编写自定义控件源码。 首先,我们需要创建一个继承自QWidget或QFrame的类来实现自定义控件。在这个类中,我们可以重载一些事件处理函数来实现控件的特定功能,比如绘制事件函数paintEvent()、鼠标事件函数mousePressEvent()等等。通过这些函数,我们可以控制控件的外观、响应用户输入等。 在实现自定义控件的外观时,可以利用Qt提供的各种绘图工具和API。例如,可以使用QPainter类来绘制各种形状、图像、文字等,还可以使用QPen和QBrush类来设置绘制的样式和颜色。通过这些工具,我们可以实现各种个性化的外观效果,如圆角渐变、阴影等。 对于自定义控件的功能实现,可以根据需求使用Qt提供的各种功能模块。比如,使用QTimer类实现定时器功能,使用QMediaPlayer类实现音视频播放功能等等。此外,Qt还提供了一系列的信号和槽机制,可以方便地实现控件之间的交互和通信。 在自定义控件的使用方面,可以通过在其他QWidget中使用该控件的对象的方式来使用它。将自定义控件放入项目中,然后在界面中添加该控件的实例对象,即可展示该控件,并与其交互。也可以通过在UI界面设计软件中将该控件拖拽到需要的位置上,然后使用信号槽机制来实现与其他控件的交互。 总之,Qt/C++编写自定义控件源码需要熟悉Qt的基本概念和API,并结合自身的需求来设计和实现控件的外观和功能。通过合理的设计和编码,可以创建出各种各样的自定义控件,丰富应用程序的界面和功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值