QT5实现自定义(Android风格)滑动开关

本文详细介绍了如何使用C++和Qt框架实现一个自定义的滑动开关组件,包括头文件(SwBtn.h)和源文件(SwBtn.cpp)的代码实现。内容涵盖了开关状态的获取和设置、颜色配置、大小调整以及鼠标事件处理,通过重写Qt的绘图和事件处理函数,实现开关的滑动效果。此外,还展示了如何在其他Widget窗口中使用该滑动开关组件。
摘要由CSDN通过智能技术生成

参考博客地址https://blog.csdn.net/liang19890820/article/details/52164289

大神提供了很好的思路,我在原文章的思路上理解若有不正确的,欢迎指正

基本原理如下:

 绘制滑动开关的原理如下:

  

 SwBtn.h文件代码如下 ——相关注释我都写了自己的理解

#ifndef SWBTN_H
#define SWBTN_H

#include <QWidget>
#include <QTimer>
class SWBtn : public QWidget
{
    Q_OBJECT
public:
    explicit SWBtn(QWidget *parent = nullptr);

    bool SwBtn_isChecked() const;                   //返回开关状态  打开——true  关闭——false

    void setSwBtn_Status(bool check);               //设置开关状态

    void setSwBtn_BackgroundColor(QColor color);    //设置背景颜色

    void setSwBtn_CheckedColor(QColor color);       //设置选中颜色

    void setSwBtn_DisabilityColor(QColor color);    //设置不可用的颜色

    void setSwBtn_WidgetSize(int m_width,int m_height); //设置整个按键窗口大小
protected:
    void paintEvent(QPaintEvent *event) override;                 //重写绘图事件——绘制按钮

    //重写鼠标左键按压事件  Q_DECL_OVERRIDE(这个宏可以用来声明一个覆盖的虚函数)  override在这里等于这个宏
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE/*等同于Q_DECL_OVERRIDE*/;   //override  c++11特性

    //切记一定要对虚函数进行重新实现  不然未重新实现虚函数 override会使得报错
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;   //重写鼠标释放事件

    void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;   //重写大小变化事件

    QSize sizeHint() const Q_DECL_OVERRIDE;           //重写返回默认推荐大小

    QSize minimumSizeHint() const Q_DECL_OVERRIDE;     //重写返回推荐的最小大小

signals:
    //当开关状态改变时,发射信号(鼠标释放)
    void SwBtn_SWITCH(bool check);

private slots:
    void SwBtn_Slide();    //槽函数实现 圆形滑动

private:
    bool m_SwBtn_Status;   //开关状态

    QColor m_SwBtn_background;     // 背景颜色

    QColor m_SwBtn_checkedColor;   // 选中颜色

    QColor m_SwBtn_disabilityColor;  // 不可用颜色

    QColor m_SwBtn_thumbColor;     // 小圆圈颜色

    qreal m_SwBtn_radius;          // 圆角

    qreal m_SwBtn_X;              // 窗口x点坐标

    qreal m_SwBtn_Y;              // 窗口y点坐标

    qint16 m_SwBtn_Height;        // 高度

    qint16 m_SwBtn_Margin;        // 外边距

    QTimer m_SwBtn_timer;          // 定时器
};

#endif // SWBTN_H

 SwBtn.cpp文件具体实现如下:相关注释也写好了

/**************头文件******************/
#include "swbtn.h"
#include <QPainter>
#include <QMouseEvent>
/*****************END*****************/
SWBtn::SWBtn(QWidget *parent) : QWidget(parent),
    m_SwBtn_Status(false),
    m_SwBtn_background(Qt::black),
//    m_SwBtn_checkedColor(0,150,136),
    m_SwBtn_checkedColor(255,000,000),
    m_SwBtn_disabilityColor(190,190,190),
    m_SwBtn_thumbColor(Qt::white),
    m_SwBtn_radius(12),     //半圆半径
    m_SwBtn_Height(24),    //窗口高度
    m_SwBtn_Margin(5)      //窗口边距
  //切记,以上构造函数要按自己的私有属性中的成员顺序来赋值,不然会报错
{
    /*this->*/setCursor(Qt::PointingHandCursor);   //设置鼠标光标在小部件上的形状  此处为手型

    //QT4 信号与槽实现  此处是时间变化改变转换开关滑动时状态
    connect(&m_SwBtn_timer,SIGNAL(timeout()),this,SLOT(SwBtn_Slide()));
}
//返回开关状态
bool SWBtn::SwBtn_isChecked() const
{
    return m_SwBtn_Status;
}
//设置开关状态
void SWBtn::setSwBtn_Status(bool check)
{
    m_SwBtn_Status=check;
    m_SwBtn_timer.start(10);
}
//设置背景颜色
void SWBtn::setSwBtn_BackgroundColor(QColor color)
{
    m_SwBtn_background=color;
}
//设置选中颜色
void SWBtn::setSwBtn_CheckedColor(QColor color)
{
    m_SwBtn_checkedColor=color;
}
//设置不可用时颜色
void SWBtn::setSwBtn_DisabilityColor(QColor color)
{
    m_SwBtn_disabilityColor=color;
}
//设置整个按键窗口宽度和高度
void SWBtn::setSwBtn_WidgetSize(int m_width, int m_height)
{
    this->m_SwBtn_Height=m_width-m_height;
    this->m_SwBtn_Margin=m_height-(m_width/2);
    this->m_SwBtn_radius=m_SwBtn_Height/2;
    update();
}

void SWBtn::paintEvent(QPaintEvent *event)
{
  /* Q_UNUSED指示编译器没有在函数体中使用指定名称的形参。
* 这可以用来抑制编译器警告,同时允许在函数的签名中定义有意义的参数名。*/
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setPen(Qt::NoPen);  //设置画笔
    painter.setRenderHint(QPainter::Antialiasing);  //设置消除边缘锯齿

    QPainterPath path;
    QColor background;  //背景色
    QColor thumbColor;  //小圆颜色

    qreal pellucidity;   //透明度参数  浮点型
    if(isEnabled()){     //是否可用状态
        if(m_SwBtn_Status){  //打开状态
           background=m_SwBtn_checkedColor;
           thumbColor=m_SwBtn_checkedColor;
           pellucidity=0.6;
        }
        else{               //关闭状态
            background=m_SwBtn_background;
            thumbColor=m_SwBtn_thumbColor;
            pellucidity=0.8;
        }
    }
    else{    //不可用状态
        background=m_SwBtn_background;
        thumbColor=m_SwBtn_disabilityColor;
        pellucidity=0.2;
    }

    //绘制背景圆角矩形
    painter.setBrush(background);   //设置画刷
    painter.setOpacity(pellucidity); //设置透明度
    //设置圆角矩形参数 QRectF(x,y,长,高)  x半径  y半径   (3,3)左上角 矩形(32*16) 半径(8,8)
    path.addRoundedRect(QRectF(m_SwBtn_Margin,
                               m_SwBtn_Margin,
                               width()-2*m_SwBtn_Margin,
                               height()-2*m_SwBtn_Margin),
                        m_SwBtn_radius,
                        m_SwBtn_radius);
    painter.drawPath(path.simplified());    //加载路径

    //绘制小圆圈
    painter.setBrush(thumbColor);
    painter.setOpacity(1);
    //绘制矩形中的椭圆 给定一个矩形  返回贴着边的椭圆  (22*22)
//    painter.drawEllipse(QRectF(m_SwBtn_X-(m_SwBtn_Height/2),
//                               m_SwBtn_Y-(m_SwBtn_Height/2),
//                               height(),
//                               height()));
    painter.drawEllipse(QRectF(m_SwBtn_X/*-(m_SwBtn_Height/2)*/,
                               m_SwBtn_Y/*-(m_SwBtn_Height/2)*/,
                               height(),
                               height()));
}
//鼠标按下事件
void SWBtn::mousePressEvent(QMouseEvent *event)
{
    if(isEnabled()){
        //判断是否左键安按下
        if(event->button()==Qt::LeftButton){  //**
            event->accept();
        }
        else
            event->ignore();
    }
}
//鼠标释放按键 发射状态改变信号
void SWBtn::mouseReleaseEvent(QMouseEvent *event)
{
    if(isEnabled()){
        if((event->type()==QMouseEvent::MouseButtonRelease)&&(event->button()==Qt::LeftButton)){
            event->accept();
            m_SwBtn_Status=!m_SwBtn_Status;    //改变当前开关状态
            emit SwBtn_SWITCH(m_SwBtn_Status); //发射改变以后的状态
            m_SwBtn_timer.start(10);           //定时器10ms响应一次
        }
        else{
            event->ignore();     //忽略该事件
        }
    }

}
//重现大小改变事件
void SWBtn::resizeEvent(QResizeEvent *event)
{
//    m_SwBtn_X=m_SwBtn_Height/2;    //x=8
//    m_SwBtn_Y=m_SwBtn_Height/2;    //y=8
    m_SwBtn_X=0;
    m_SwBtn_Y=0;
    QWidget::resizeEvent(event);
}
//返回默认建议大小
QSize SWBtn::sizeHint() const
{
    return minimumSizeHint();
}
//返回建议最小大小
QSize SWBtn::minimumSizeHint() const
{
    //若按构造函数指定大小   则尺寸为2*(16+3),16+2*3   尺寸为(38*22)像素
    return QSize(2*(m_SwBtn_Height+m_SwBtn_Margin),m_SwBtn_Height+2*m_SwBtn_Margin);
}
//滑动槽函数定义 改变小圆圈的位置 每10ms刷新一次绘图事件
void SWBtn::SwBtn_Slide()
{
//    if(m_SwBtn_Status){  //打开状态
//        m_SwBtn_X+=1;
//        if(m_SwBtn_X>=width()-m_SwBtn_Height)  //x到22时
//        m_SwBtn_timer.stop();
//    }
//    else{
//        m_SwBtn_X-=1;
//        if(m_SwBtn_X<=m_SwBtn_Height/2)    //x到8时
//           m_SwBtn_timer.stop();
//    }
    if(m_SwBtn_Status){  //打开状态
        m_SwBtn_X+=1;
        if(m_SwBtn_X>=width()-height())  //x到16时    直接更新X坐标为宽度减高度
        m_SwBtn_timer.stop();
    }
    else{
        m_SwBtn_X-=1;
        if(m_SwBtn_X<=0)    //x到0时     X坐标直接从0开始
           m_SwBtn_timer.stop();
    }
    update();    //更新绘图事件
}













具体的实现代码,在别的Widget窗口实现如下:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    BTN1=new SWBtn(ui->widget_1);
    BTN2=new SWBtn(ui->widget_1);
    BTN1->move(50,50);
    BTN2->move(50,100);
    BTN3=new MY_SwitchButton(ui->widget_1);
    BTN3->move(50,150);
}

Widget::~Widget()
{
    delete ui;
}

具体实现的效果图如下所示:

 欢迎交流讨论,目前也是一个正在学习QT的学习者。欢迎大家过来指正讨论。

Qt实现滑动开关的功能,可以使用QCheckBox控件和QStyleSheet来实现。 首先在Qt Designer中拖拽一个QCheckBox控件到窗口上,然后在属性编辑器中设置QCheckBox的样式为无边框,并设置背景色和圆角等属性。 然后在Qt代码中,可以使用QStyleSheet来设置滑动开关的样式。例如: ```cpp // 设置样式表 ui->checkBox->setStyleSheet("QCheckBox::indicator {" "background-color: white;" "border: 1px solid gray;" "width: 50px;" "height: 30px;" "border-radius: 15px;" "}" "QCheckBox::indicator:checked {" "background-color: green;" "}" "QCheckBox::indicator:unchecked {" "background-color: gray;" "}" "QCheckBox::indicator:checked:disabled {" "background-color: darkgreen;" "}" "QCheckBox::indicator:unchecked:disabled {" "background-color: darkgray;" "}" ); ``` 其中,QCheckBox::indicator是QCheckBox控件的指示器部分,可以设置其背景色、边框、宽度、高度和圆角等属性。QCheckBox::indicator:checked表示选中状态下的样式,QCheckBox::indicator:unchecked表示未选中状态下的样式。还可以设置禁用状态下的样式,例如QCheckBox::indicator:checked:disabled表示选中状态下的禁用样式。 最后,可以在Qt代码中处理QCheckBox的状态变化信号来实现滑动开关的功能。例如: ```cpp connect(ui->checkBox, &QCheckBox::stateChanged, [=](int state) { if (state == Qt::Checked) { // 开关打开状态 } else { // 开关关闭状态 } }); ``` 这样就可以实现滑动开关的功能了。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值