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


    概述


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

    自定义滑动按钮

    c++/Qt实现


    .h文件

    #ifndef SwitchButtonInsideINSIDE_H
    #define SwitchButtonInsideINSIDE_H
    
    #include 
    
    #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 
    #include 
    #include 
    #include 
    
    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);
    }
    
  • 相关阅读:
    基于PaddleOCR开发easy click文字识别插件
    数学建模国赛 2020B-穿越沙漠 第一关 Lingo 和 C语言 动态规划求解
    Windows电脑上的多开器与分布式存储系统的关系
    Java—List
    记录一次由cnpm引发的问题
    产品周报第38期|阅读总数规则校验功能上线,热榜算法更新,付费问题退款支持原路返回……
    c#设计模式-创建型模式 之 建造者模式
    oak深度相机入门教程-Gen2 相机
    Spring第六讲:Spring事务原理及应用
    [杂记]C++中关于虚函数的一些理解
  • 原文地址:https://blog.csdn.net/SuperYang_/article/details/139618807