IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> QT5实现自定义(Android风格)滑动开关 -> 正文阅读

[C++知识库]QT5实现自定义(Android风格)滑动开关

参考博客地址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的学习者。欢迎大家过来指正讨论。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:03:37  更:2021-08-09 10:04:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 19:50:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码