Qt实现SwitchButton滑动开关按钮组件

概述


使用Qt如何制作一个滑动开关按钮,同类的文章和代码网上很多,但很多都是pyqt编写的,也有c++编写的,大家可以参考. 我这里主要是实现了一个滑动按钮,富有滑动动画和文字,话不多说,上代码

自定义滑动按钮

c++/Qt实现


.h文件

#ifndef SwitchButtonInsideINSIDE_H
#define SwitchButtonInsideINSIDE_H

#include <QWidget>

#include "customcomponent_global.h"

class Slider;

class CUSTOMCOMPONENT_EXPORT SwitchButtonInside : public QWidget
{
    Q_OBJECT

public:
    explicit SwitchButtonInside(QWidget *parent = nullptr);
    ~SwitchButtonInside();
    /**
     * @brief SetSize 设置按钮的尺寸
     * @param nWidth 按钮的新宽度
     * @param nHeight 按钮的新高度
     */
    void SetSize(int nWidth, int nHeight);

    /**
     * @brief SetActiveColor 设置按钮激活时候的颜色
     * @param color 激活颜色
     */
    void SetActiveColor(const QColor& color);

    /**
     * @brief SetInactiveColor 设置按钮未激活时候的颜色
     * @param color 未激活颜色
     */
    void SetInactiveColor(const QColor& color);

    /**
     * @brief SetSliderColor 设置滑块颜色
     * @param color 滑块的颜色
     */
    void SetSliderColor(const QColor& color);

    /**
     * @brief SetStatus 设置按钮状态
     * @param bActive true: 激活,false: 未激活
     */
    void SetStatus(bool bActive);

    /**
     * @brief GetStatus 获取按钮当前状态
     * @return  true: 激活,false: 未激活
     */
    bool GetStatus() const;

    /**
     * @brief SetStatus 设置按钮显示文字
     * @param text: 文字内容
     */
    void SetText(const QString &text);

protected:
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

    void ToActive();
    void ToInactive();

private:
    bool m_bActive; // 是否激活
    int m_nArcRadius; // 圆弧的半径
    int m_nRectWidth; // 矩形的宽度
    const short m_nMargin = 2;
    const int m_nDuration = 100; // 动画时间,单位毫秒
    bool m_bClicked; // 能否被点击。如果动画还没结束,无法进行点击/状态切换
    QColor m_colorActive; // 激活时的颜色
    QColor m_colorInactive;
    Slider* m_pSlider;
    QString m_text; // 显示文字

signals:
    /**
     * @brief Clicked 按钮被点击后发出的信号
     * @param status 当前按钮状态。true为active,false为inactive
     */
    void Clicked(bool status);
};


class Slider : public QWidget
{
    Q_OBJECT
public:
    explicit Slider(QWidget* parent = nullptr);
    ~Slider();

    /**
     * @brief SetSliderColor 设置滑块颜色
     * @param color
     */
    void SetSliderColor(const QColor& color);

protected:
    void paintEvent(QPaintEvent* e) override;

private:
    QColor m_sliderColor;
};

#endif // SwitchButtonInsideINSIDE_H

.cpp文件

#include "switchbuttoninside.h"
#include <QPainter>
#include <QFont>
#include <QPainterPath>
#include <QPropertyAnimation>

SwitchButtonInside::SwitchButtonInside(QWidget *parent) :
    QWidget(parent)
{
    resize(72, 28); // 默认80,28宽高
    m_pSlider = new Slider(this);
    m_pSlider->resize(height() - m_nMargin * 2, height() - m_nMargin * 2);
    m_pSlider->move(m_nMargin, m_nMargin);
    m_bActive = false; // 默认未激活
    m_nArcRadius = std::min(width(), height()); // 默认半径
    m_nRectWidth = width() - m_nArcRadius;
    m_colorActive = qRgb(60, 189, 136);
    m_colorInactive = qRgb(167, 177, 188);
}

SwitchButtonInside::~SwitchButtonInside()
{
}

void SwitchButtonInside::SetSize(int nWidth, int nHeight)
{
    resize(nWidth, nHeight);
    m_pSlider->resize(height() - m_nMargin * 2, height() - m_nMargin * 2);
    m_pSlider->move(m_nMargin, m_nMargin);
    m_nArcRadius = std::min(width(), height());
    m_nRectWidth = width() - m_nArcRadius;
}

void SwitchButtonInside::SetActiveColor(const QColor& color)
{
    m_colorActive = color;
}

void SwitchButtonInside::SetInactiveColor(const QColor& color)
{
    m_colorInactive = color;
}

void SwitchButtonInside::SetSliderColor(const QColor& color)
{
    m_pSlider->SetSliderColor(color);
}

void SwitchButtonInside::SetStatus(bool bActive)
{
    if(m_bActive == bActive) {
        return;
    }
    m_bActive = bActive;
    if(m_bActive) {
        ToActive();
    } else {
        ToInactive();
    }
}

bool SwitchButtonInside::GetStatus() const
{
    return m_bActive;
}

void SwitchButtonInside::SetText(const QString &text)
{
    m_text = text;
}

void SwitchButtonInside::paintEvent(QPaintEvent *)
{
    qDebug() << "[SwitchButtonInside]m_nArcRadius = " << m_nArcRadius
             << "| m_nRectWidth << " << m_nRectWidth
             << "| size = " << width() << "," << height();

    if (m_nArcRadius > height()) {
        qDebug() << "******* switchbutton resize ******";
        SetSize(width(), height());
    }

    QPainter p;
    p.begin(this);
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setPen(Qt::NoPen);
    if(m_bActive) p.setBrush(QBrush(m_colorActive));
    else p.setBrush(QBrush(m_colorInactive));

    QPainterPath leftPath;
    leftPath.addEllipse(0, 0, m_nArcRadius, m_nArcRadius);

    QPainterPath middlePath;
    middlePath.addRect(m_nArcRadius / 2, 0, m_nRectWidth, m_nArcRadius);

    QPainterPath rightPath;
    rightPath.addEllipse(m_nRectWidth, 0, m_nArcRadius, m_nArcRadius);

    QPainterPath path = leftPath + middlePath + rightPath;

    p.drawPath(path);

    QPen pen;
    pen.setColor(Qt::white);
    p.setPen(pen);
    QFont ft;
    ft.setPointSize(9);
    p.setFont(ft);
    if (m_bActive) {
        p.drawText(QRect(0, 0, m_nRectWidth,
                         m_nArcRadius), Qt::AlignCenter, m_text);
    } else {
        p.drawText(QRect(m_nArcRadius, 0,
                         m_nRectWidth, m_nArcRadius), Qt::AlignCenter, m_text);
    }


    p.end();
}

void SwitchButtonInside::mousePressEvent(QMouseEvent *event)
{
    QWidget::mousePressEvent(event);
}

void SwitchButtonInside::mouseReleaseEvent(QMouseEvent *event)
{
    emit Clicked(!m_bActive);
    QWidget::mouseReleaseEvent(event);
}

void SwitchButtonInside::ToActive()
{
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pSlider, "geometry");
    pAnimation->setDuration(m_nDuration);
    pAnimation->setStartValue(m_pSlider->rect());
    pAnimation->setEndValue(QRect(width() - m_pSlider->width() - m_nMargin,
                                  m_nMargin,
                                  m_pSlider->width(),
                                  m_pSlider->height()));
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, [&](const QVariant &value){
        Q_UNUSED(value)
        update();
    });
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}

void SwitchButtonInside::ToInactive()
{
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pSlider, "geometry");
    pAnimation->setDuration(m_nDuration);
    pAnimation->setStartValue(QRect(m_pSlider->x(),
                                    m_pSlider->y(),
                                    m_pSlider->width(),
                                    m_pSlider->height()));
    pAnimation->setEndValue(QRect(m_nMargin,
                                  m_nMargin,
                                  m_pSlider->width(),
                                  m_pSlider->height()));
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, [&](const QVariant &value){
        Q_UNUSED(value)
        update();
    });
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}


///
/// Slider  滑块类  //
//

Slider::Slider(QWidget *parent) : QWidget(parent)
{
    m_sliderColor = Qt::white;
    resize(56, 56);
}

Slider::~Slider()
{

}

void Slider::SetSliderColor(const QColor &color)
{
    m_sliderColor = color;
    update();
}

void Slider::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    p.fillRect(rect(), Qt::transparent);
    p.setBrush(m_sliderColor);
    p.setPen(Qt::NoPen);
    p.drawRoundedRect(rect(), width() / 2, height() / 2);
    QWidget::paintEvent(e);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperYang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值