Qt仿iOS的Switch开关实现

Qt仿iOS的Switch开关实现,第1张

最近因为在玩iOS手机,突然觉得人家的开关就是很好看,于是乎自己花了点时间写了一下,下面是效果图,代码中没有使用定时器,而是直接用的属性动画,并且支持横向和竖向动态缩放。

实现代码如下:
Switch.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

enum class AnimationType
{
    NoAnimation, //没有动画
    PropertyAnimation, //属性动画
};

class QPropertyAnimation;
class Switch : public QWidget
{
    Q_OBJECT

public:
    Switch(QWidget *parent = nullptr);
    ~Switch();

protected:
    virtual void paintEvent(QPaintEvent *e) override;
    virtual void resizeEvent(QResizeEvent *e) override;
    virtual void mousePressEvent(QMouseEvent *e) override;

private slots:
    void OnValueChanged(QVariant);

private:
    void CalcSliderPos();
    void PaintLeftArea(QPainter&,int);
    void PaintRightArea(QPainter&,int);
    void PaintSliderArea(QPainter&,int);

private:
    bool m_IsOpen; //当前状态
    int m_SliderPos; //滑块当前位置
    QColor m_CloseBgColor; //关闭后背景颜色
    QColor m_OpenBgColor; //打开后背景颜色
    QColor m_SliderBgColor; //滑块背景颜色
    AnimationType m_AnimationType; //动画类型
    QPropertyAnimation* m_PropertyAnimation;
};
#endif // WIDGET_H

Swtich.cpp

#include "Switch.h"
#include 
#include 
#include 

Switch:: Switch(QWidget *parent)
    : QWidget(parent)
    , m_IsOpen(false)
    , m_SliderPos(0)
    , m_CloseBgColor(Qt::gray)
    , m_OpenBgColor(Qt::green)
    , m_SliderBgColor(Qt::white)
    , m_AnimationType(AnimationType::PropertyAnimation)
    , m_PropertyAnimation(Q_NULLPTR)
{
    switch(m_AnimationType)
    {
    case AnimationType::NoAnimation:
        break;
    case AnimationType::PropertyAnimation:
        m_PropertyAnimation = new QPropertyAnimation(this,"");
        connect(m_PropertyAnimation,&QPropertyAnimation::valueChanged,this,&Switch::OnValueChanged);
        break;
    default:
        break;
    }
}

Switch::~ Switch()
{}

void Switch::CalcSliderPos()
{
    int size=qMin(width(),height());
    if(m_IsOpen){
        if(width()height()-size;
        }
        else{
            m_SliderPos = width()-size;
        }
    }
    else{
        m_SliderPos = 0;
    }
}

void Switch::resizeEvent(QResizeEvent *e)
{
    CalcSliderPos();
    QWidget::resizeEvent(e);
}

void Switch::mousePressEvent(QMouseEvent *e)
{
    if(Qt::LeftButton==e->button()){
        m_IsOpen=!m_IsOpen;
        switch(m_AnimationType)
        {
        case AnimationType::NoAnimation:
            CalcSliderPos();
            update();
            break;
        case AnimationType::PropertyAnimation:
            if(Q_NULLPTR==m_PropertyAnimation){
                CalcSliderPos();
                update();
            }
            else{
                m_PropertyAnimation->stop();
                if(m_IsOpen){
                    m_PropertyAnimation->setStartValue(0);
                    m_PropertyAnimation->setEndValue(qAbs(width()-height()));
                }
                else{
                    m_PropertyAnimation->setStartValue (qAbs(width()-height()));
                    m_PropertyAnimation->setEndValue(0);
                }
                m_PropertyAnimation->setDuration(200);
                m_PropertyAnimation->start();
            }
            break;
        default:
            break;
        }
    }
}

void Switch::OnValueChanged(QVariant value)
{
    m_SliderPos=value.toInt();
    update();
}

void Switch::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    //设置反走样
    painter.setRenderHint(QPainter::Antialiasing,  true);
    int size=qMin(width(),height());
    PaintLeftArea(painter,size);
    PaintRightArea(painter,size);
    PaintSliderArea(painter,size);
    QWidget::paintEvent(e);
}

void Switch::PaintLeftArea(QPainter& painter,int size)
{
    painter.save();
    //计算左边外框线
    QPainterPath painterPath;
    painterPath.addEllipse(0,0,size,size);
    if(width()

这里的私有变量可以通过共有接口设置以供外部调用设置颜色等。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/989541.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)