Qt QWidget实现开关控件SwithButton(SlipButton)

Qt 专栏收录该内容
118 篇文章 25 订阅

前言

Qt做界面的时候常常会用到开关控件,类似于CheckButton有两种状态,只是界面表现形式不一样而已。本文通过QWidget类来实现一个开关控件SwitchBtn(有些平台上又称为SlipButton)。
首先来看看封装好的控件样式
这里写图片描述

正文

其中动画效果是通过QPropertyAnimation来实现的,按钮中间的圆是一张准备好的图片,而控件背景是通过当前状态然后用QPainter来绘制的。
话不多说,直接上代码

头文件

#include <QWidget>
#include <QPaintEvent>
#include <QPainterPath>
#include <QPropertyAnimation>
#include <QMouseEvent>
#include <QLabel>

class CTLSlipBtn : public QWidget
{
    Q_OBJECT
public:
    explicit CTLSlipBtn(int w,int h,QWidget *parent = 0);
    ~CTLSlipBtn();
    void setBtnChecked(bool check);

protected:
    void paintEvent(QPaintEvent* e);
    void mouseReleaseEvent(QMouseEvent * e);
signals:
    void sigClicked(bool);
private:
    void _checkBtn();
private:
    QLabel * m_pSwitchBtn;
    bool m_bIsChecked;
    QPainterPath* m_pTBtnBg;
    QPropertyAnimation* m_pBtnAni;
};

源文件

#include "ctlslipbtn.h"
#include <QPainter>
#include "alcommonparameter.h"

CTLSlipBtn::CTLSlipBtn(int w, int h, QWidget *parent) :
    QWidget(parent),
    m_bIsChecked(false)
{
    resize(w,h);
    m_pSwitchBtn = new QLabel(this);
    m_pSwitchBtn->setFixedSize(h,h);
    m_pSwitchBtn->setPixmap(QPixmap("btn_switch.png"));
    m_pSwitchBtn->move(QPointF(1,0).toPoint());
    m_pTBtnBg = new QPainterPath();
    m_pTBtnBg->moveTo(width(),height());
    m_pTBtnBg->setFillRule(Qt::WindingFill);
    m_pTBtnBg->addEllipse(w- h,0,h,h);
    m_pTBtnBg->addEllipse(0,0,h,h);
    m_pTBtnBg->addRect(h*0.5,0,w-h ,h);

    m_pBtnAni = new QPropertyAnimation(m_pSwitchBtn,"pos",this);
    m_pBtnAni->setEasingCurve(QEasingCurve::Linear);
    m_pBtnAni->setDuration(100);
}

CTLSlipBtn::~CTLSlipBtn()
{
    delete m_pBtnAni;
    delete m_pTBtnBg;
}

void CTLSlipBtn::setBtnChecked(bool check)
{
    m_bIsChecked = check;
    if(check)
    {
        m_pSwitchBtn->move(QPointF(width()-m_pSwitchBtn->height()-1,0).toPoint());
    }
    else
    {
        m_pSwitchBtn->move(QPointF(1,0).toPoint());
    }
}

void CTLSlipBtn::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    if(m_bIsChecked)
    {
       painter.setBrush(QColor(34,169,173));
    }
    else
    {
        painter.setBrush(QColor(200,200,200));
    }
    painter.drawPath(*m_pTBtnBg);
    QWidget::paintEvent(e);
}

void CTLSlipBtn::mouseReleaseEvent(QMouseEvent *e)
{
    _checkBtn();
    update();
    emit sigClicked(m_bIsChecked);
    QWidget::mouseReleaseEvent(e);
}

void CTLSlipBtn::_checkBtn()
{
    if(m_pBtnAni)
    {
        if(m_pBtnAni->state() == QAbstractAnimation::Running)
        {
            return;
        }
        if(m_bIsChecked)
        {
             m_pBtnAni->setStartValue(QPointF(width()-height()-1,0).toPoint());
             m_pBtnAni->setEndValue(QPointF(1,0).toPoint());
        }
        else
        {
            m_pBtnAni->setStartValue(QPointF(1,0).toPoint());
            m_pBtnAni->setEndValue(QPointF(width()-height()-1,
                                           0).toPoint());
        }
        m_pBtnAni->start();
        m_bIsChecked = !m_bIsChecked;
    }
}

其中开关状态变化后会发出信号sigClicked(bool)
这里的控件背景都是固定写死的,为了灵活性,可以写一个接口单独控件背景颜色,比较简单,这里不再赘述。控件使用方式也很简单,直接初始化的时候传入控件的大小,然后连接对象的信号即可。

  • 3
    点赞
  • 3
    评论
  • 3
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值