当前位置: 首页 > news >正文

[Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

1、功能介绍

在项目UI中使用较多的打开/关闭的开关按钮,一般都是找图片去做效果,比如说如下的图像来表征打开或关闭。

图一.png图二.png图三.PNG

如果想要控件有打开/关闭的动画效果或比较好的视觉效果,这里就可以使用自定义控件,使用Painter来绘制控件。软件最终的效果如上图三:

2、主要的实现绘制代码

绘制背景区域

void SwitchButton::drawBackGround(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;if (isEnabled()) {bgColor.setAlpha(140);}painter->setBrush(bgColor);QRect rect(0, 0, width(), height());int side = qMin(width(), height());//左侧半圆QPainterPath path1;path1.addEllipse(rect.x(), rect.y(), side, side);//右侧半圆QPainterPath path2;path2.addEllipse(rect.width() - side, rect.y(), side, side);//中间的矩形QPainterPath path3;path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, height());QPainterPath path = path1 + path2 + path3;painter->drawPath(path);//绘制文本//滑块半径int sliderWidth = qMin(height(), width()) - m_space * 2 - 5;if (m_checked){QRect textRect(0, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOn);} else {QRect textRect(sliderWidth, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOff);}painter->restore();
}

绘制滑块

void SwitchButton::drawSlider(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor color = m_checked ? m_sliderColorOn : m_sliderColorOff;painter->setBrush(QBrush(color));int sliderWidth = qMin(width(), height()) - m_space * 2;QRect rect(m_space + m_startX, m_space, sliderWidth, sliderWidth);painter->drawEllipse(rect);painter->restore();
}

这里引入了滑块动画效果,设定一个定时器,根据滑块的距离设置一个动画的效果

    m_timer = new QTimer(this);m_timer->setInterval(30);connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateValue()));void SwitchButton::UpdateValue()
{if (m_checked) {if (m_startX < m_endX) {m_startX += m_step;} else {m_startX = m_endX;m_timer->stop();}} else {if (m_startX > m_endX) {m_startX -= m_step;} else {m_startX = m_endX;m_timer->stop();}}update();
}

3、功能实现源码

switchButton.h

#ifndef SWITCHBUTTON_H
#define SWITCHBUTTON_H#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QColor>class SwitchButton : public QWidget
{Q_OBJECT
public:explicit SwitchButton(QWidget *parent = nullptr);signals:void statusChanged(bool checked);public slots:private slots:void UpdateValue();private:void drawBackGround(QPainter *painter);void drawSlider(QPainter *painter);protected:void paintEvent(QPaintEvent *event);void mousePressEvent(QMouseEvent *event);private://滑块距离边界距离int m_space;//圆角角度int m_radius;//是否选中bool m_checked;//是否显示文本bool m_showText;//是否显示圆bool m_showCircle;//是否使用动画bool m_animation;//打开时候背景色QColor m_bgColorOn;//关闭时候背景色QColor m_bgColorOff;//打开时候滑块颜色QColor m_sliderColorOn;//关闭时候滑块颜色QColor m_sliderColorOff;//文字颜色QColor m_textColor;//打开时候文字QString m_textOn;//关闭时候文字QString m_textOff;//动画定时器QTimer *m_timer;//动画步长int m_step;//滑块开始X轴坐标int m_startX;//滑块介绍X轴坐标int m_endX;public:int space()                 const;int radius()                const;bool checked()              const;bool showText()             const;bool showCircle()           const;bool animation()            const;QColor bgColorOn()          const;QColor bgColorOff()         const;QColor sliderColorOn()      const;QColor sliderColorOff()     const;QColor textColor()          const;QString textOn()            const;QString textOff()           const;int step()                  const;int startX()                const;int endX()                  const;public Q_SLOTS:void setSpace(int space);void setRadius(int radius);void setChecked(bool checked);void setShowText(bool show);void setShowCircle(bool show);void setAnimation(bool ok);void setBgColorOn(const QColor &color);void setBgColorOff(const QColor &color);void setSliderColorOn(const QColor &color);void setSliderColorOff(const QColor &color);void setTextColor(const QColor &color);void setTextOn(const QString &text);void setTextOff(const QString &text);//    void setStep(int step);
//    void setStartX(int startX);
//    void setEndX(int endX);
};#endif // SWITCHBUTTON_H

switchButton.cpp

#pragma execution_character_set("utf-8")
#include "SwitchButton.h"
#include <QPainter>SwitchButton::SwitchButton(QWidget *parent) : QWidget(parent)
{m_space = 2;m_radius = 5;m_checked = false;m_showText = true;m_showText = false;m_animation = true;m_bgColorOn = QColor(21, 156, 119);m_bgColorOff = QColor(111, 122, 126);m_sliderColorOn = QColor(255, 255, 255);m_sliderColorOff = QColor(255, 255, 255);m_textColor = QColor(255, 255, 255);m_textOn = "开启";m_textOff = "关闭";m_step = 0;m_startX = 0;m_endX = 0;m_timer = new QTimer(this);m_timer->setInterval(30);connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateValue()));
}void SwitchButton::drawBackGround(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;if (isEnabled()) {bgColor.setAlpha(140);}painter->setBrush(bgColor);QRect rect(0, 0, width(), height());int side = qMin(width(), height());//左侧半圆QPainterPath path1;path1.addEllipse(rect.x(), rect.y(), side, side);//右侧半圆QPainterPath path2;path2.addEllipse(rect.width() - side, rect.y(), side, side);//中间的矩形QPainterPath path3;path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, height());QPainterPath path = path1 + path2 + path3;painter->drawPath(path);//绘制文本//滑块半径int sliderWidth = qMin(height(), width()) - m_space * 2 - 5;if (m_checked){QRect textRect(0, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOn);} else {QRect textRect(sliderWidth, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOff);}painter->restore();
}void SwitchButton::drawSlider(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor color = m_checked ? m_sliderColorOn : m_sliderColorOff;painter->setBrush(QBrush(color));int sliderWidth = qMin(width(), height()) - m_space * 2;QRect rect(m_space + m_startX, m_space, sliderWidth, sliderWidth);painter->drawEllipse(rect);painter->restore();
}void SwitchButton::paintEvent(QPaintEvent *ev)
{//启用反锯齿QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);//绘制背景drawBackGround(&painter);//绘制滑块drawSlider(&painter);
}void SwitchButton::mousePressEvent(QMouseEvent *ev)
{Q_UNUSED(ev)m_checked = !m_checked;emit statusChanged(m_checked);//计算步长m_step = width() / 10;//计算滑块X轴终点坐标if (m_checked) {m_endX = width() - height();} else {m_endX = 0;}//判断是否使用动画if (m_animation) {m_timer->start();} else{m_startX = m_endX;update();}
}void SwitchButton::UpdateValue()
{if (m_checked) {if (m_startX < m_endX) {m_startX += m_step;} else {m_startX = m_endX;m_timer->stop();}} else {if (m_startX > m_endX) {m_startX -= m_step;} else {m_startX = m_endX;m_timer->stop();}}update();
}int SwitchButton::space() const
{return m_space;
}int SwitchButton::radius() const
{return m_radius;
}bool SwitchButton::checked() const
{return m_checked;
}bool SwitchButton::showText() const
{return m_showText;
}bool SwitchButton::showCircle() const
{return m_showCircle;
}bool SwitchButton::animation() const
{return m_animation;
}QColor SwitchButton::bgColorOn() const
{return m_bgColorOn;
}QColor SwitchButton::bgColorOff() const
{return m_bgColorOff;
}QColor SwitchButton::sliderColorOn() const
{return m_sliderColorOn;
}QColor SwitchButton::sliderColorOff() const
{return m_sliderColorOff;
}QColor SwitchButton::textColor() const
{return m_textColor;
}QString SwitchButton::textOn() const
{return m_textOn;
}QString SwitchButton::textOff() const
{return m_textOff;
}int SwitchButton::step() const
{return m_step;
}int SwitchButton::startX() const
{return m_startX;
}int SwitchButton::endX() const
{return m_endX;
}void SwitchButton::setSpace(int space)
{if (m_space != space) {m_space = space;update();}
}void SwitchButton::setRadius(int radius)
{if (m_radius != radius) {m_radius = radius;update();}
}void SwitchButton::setChecked(bool checked)
{if (m_checked != checked) {m_checked = checked;update();}
}void SwitchButton::setShowText(bool show)
{if (m_showText != show) {m_showText = show;update();}
}void SwitchButton::setShowCircle(bool show)
{if (m_showCircle != show) {m_showCircle = show;update();}
}void SwitchButton::setAnimation(bool ok)
{if (m_animation != ok) {m_animation = ok;update();}
}void SwitchButton::setBgColorOn(const QColor &color)
{if (m_bgColorOn != color) {m_bgColorOn = color;update();}
}void SwitchButton::setBgColorOff(const QColor &color)
{if (m_bgColorOff != color) {m_bgColorOff = color;update();}
}void SwitchButton::setSliderColorOn(const QColor &color)
{if (m_sliderColorOn != color) {m_sliderColorOn = color;update();}
}void SwitchButton::setSliderColorOff(const QColor &color)
{if (m_sliderColorOff != color) {m_sliderColorOff = color;update();}
}void SwitchButton::setTextColor(const QColor &color)
{if (m_textColor != color) {m_textColor = color;update();}
}void SwitchButton::setTextOn(const QString &text)
{if (m_textOn != text) {m_textOn = text;update();}
}void SwitchButton::setTextOff(const QString &text)
{if (m_textOff != text) {m_textOff = text;update();}
}//void SwitchButton::setStep(int step)
//{
//    if (m_step != step) {
//        m_step = step;
//        update();
//    }
//}//void SwitchButton::setStartX(int startX)
//{//}//void SwitchButton::setEndX(int endX)
//{//}

4、效果与源码

控件实现的动态效果如下
控件效果
本小例程的代码放到我的开源gitte项目里,欢迎一起学习,也希望能收获你的小星星。
源码SwitchButton

相关文章:

[Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

1、功能介绍 在项目UI中使用较多的打开/关闭的开关按钮&#xff0c;一般都是找图片去做效果&#xff0c;比如说如下的图像来表征打开或关闭。 如果想要控件有打开/关闭的动画效果或比较好的视觉效果&#xff0c;这里就可以使用自定义控件&#xff0c;使用Painter来绘制控件。软…...

【工具】mac 环境配置

【待补充 】 一、maven配置 vim ~/.bash_profile export M3_HOME/Users/chenyang/java_utils/apache-maven-3.6.1 export PATH$PATH:$M3_HOME/bin ​ //mvn -v提示Permission denied 没有权限访问 chmod ax /Users/chenyang/java_utils/apache-maven-3.6.1/bin/mvn 二、java…...

【前端寻宝之路】学习和总结HTML的标签属性

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…...

kafka2.x版本配置SSL进行加密和身份验证

背景&#xff1a;找了一圈资料&#xff0c;都是东讲讲西讲讲&#xff0c;最后我还没搞好&#xff0c;最终决定参考官网说明。 官网指导手册地址&#xff1a;Apache Kafka 需要预备的知识&#xff0c;keytool和openssl 关于keytool的参考&#xff1a;keytool的使用-CSDN博客 …...

Linux和Windows下的文件批量重命名

一、Linux下文件批量重命名 rename命令说明&#xff1a; Usage: rename [options] … Rename files. Options: -v, --verbose explain what is being done -s, --symlink act on the target of symlinks -n, --no-act do not make any changes -o, --no-overwrite don’t overw…...

stm32之GPIO电路介绍

文章目录 1 GPIO介绍2 GPIO的工作模式2.1 浮空输入2.2 上拉输入2.3 下拉输入2.4 模拟输入2.5 开漏输出2.6 推挽输出2.7 复用开漏输出2.8 复用推挽输出2.9 其他 3 应用方式4 常用库函数 1 GPIO介绍 保护二极管&#xff1a;保护引脚&#xff0c;让引脚的电压位于正常的范围施密特…...

Unity Toggle处理状态变化事件

Toggle处理状态变化事件&#xff0c;有两个方法。 法一、通过Inspector面板设置 实现步骤&#xff1a; 在Inspector面板中找到Toggle组件的"On Value Changed"事件。单击""按钮添加一个新的监听器。拖动一个目标对象到"None (Object)"字段&am…...

UE5.1 iClone8 正确导入角色骨骼与动作

使用iClone8插件Auto Setup 附录下载链接 里面有两个文件夹,使用Auto Setup C:\Program Files\Reallusion\Shared Plugins 在UE内新建Plugins,把插件复制进去 在工具栏出现这三个人物的图标就安装成功了 iClone选择角色,导入动作 选择导出FBX UE内直接导入 会出现是否启动插件…...

FFmpeg-- c++实现:pcm和yuv编码

文章目录 流程音频视频 api核心代码audioencoder.haudioencoder.cppvideoencoder.hvideoencoder.cpp pcm和yuv编码为aac和h264&#xff0c;封装为c的AudioEncoder类和VideoEncoder类 流程 音频 初始化音频参数 int InitAAC(int channels, int sample_rate, int bit_rate); 音…...

图解CodeWhisperer的安装使用

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4d8; CodeWhisperer简介 &#…...

Python内置对象

Python是一种强大的、动态类型的高级编程语言&#xff0c;其内置对象是构成程序的基础元素。Python的内置对象包括数字、字符串、列表、元组、字典、集合、布尔值和None等&#xff0c;每种对象都有特定的类型和用途。 01 什么是内置对象 这些对象是编程语言的基础构建块&…...

开源数据集 nuScenes 之 3D Occupancy Prediction

数据总体结构 Nuscenes 数据结构 可以看一下我的blog如何下载完整版 mmdetection3d ├── mmdet3d ├── tools ├── configs ├── data │ ├── nuscenes │ │ ├── maps │ │ ├── samples │ │ ├── sweeps │ │ ├── lidarseg (o…...

物联网竞赛板CubMx全部功能简洁配置汇总

目录 前言&#xff1a;1、按键&LED灯配置&#xff1a;2、OLED配置&#xff1a;3、继电器配置&#xff1a;4、LORA模块配置&#xff1a;5、矩阵模块&#xff1a;6、串口模块&#xff1a;7、RTC配置&#xff1a;8、ADC模块配置&#xff1a;9、温度传感器模块&#xff1a;后续…...

使用Redis做缓存的小案例

如果不了解Redis&#xff0c;可以查看本人博客&#xff1a;Redis入门 Redis基于内存&#xff0c;因此查询速度快&#xff0c;常常可以用来作为缓存使用&#xff0c;缓存就是我们在内存中开辟一段区域来存储我们查询比较频繁的数据&#xff0c;这样&#xff0c;我们在下一次查询…...

剧本杀小程序功能介绍

剧本杀功能介绍 剧本杀&#xff0c;一种融合了角色扮演与推理解谜的社交游戏&#xff0c;近年来在年轻人中越来越受欢迎。它不仅可以锻炼参与者的逻辑推理能力&#xff0c;还能增进朋友间的感情&#xff0c;提升团队协作能力。下面&#xff0c;我们将详细介绍剧本杀的核心功能…...

C#基础语法学习笔记(传智播客学习)

最近在学习C#开发知识&#xff0c;跟着传智播客的视频学习了一下&#xff0c;感觉还不错&#xff0c;整理一下学习笔记。 C#基础语法学习笔记 1.背景知识2.Visual Studio使用3.基础知识4.变量5.运算符与表达式6.程序调试7.判断结构8.循环结构9.常量、枚举类型10.结构体类型11.数…...

图论01-DFS和BFS(深搜和广搜邻接矩阵和邻接表/Java)

1.深度优先理论基础(dfs) dfs的两个关键操作 搜索方向&#xff0c;是认准一个方向搜&#xff0c;直到碰壁之后再换方向 换方向是撤销原路径&#xff0c;改为节点链接的下一个路径&#xff0c;回溯的过程。dfs解题模板 void dfs(参数) {if (终止条件) {存放结果;return;}for …...

【Python】Miniconda+Vscode+Jupyter 环境搭建

1.安装 Miniconda Conda 是一个开源的包管理和环境管理系统&#xff0c;可在 Windows、macOS 和 Linux 上运行&#xff0c;它可以快速安装、运行和更新软件包及其依赖项。使用 Conda&#xff0c;我们可以轻松在本地计算机上创建、保存、加载和切换不同的环境 Conda 分为 Anaco…...

Redis消息队列与thinkphp/queue操作

业务场景 场景一 用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。 遇到两个问题&#xff1a; 由于代码是串行方式&#xff0c;流程大致为&#xff1a;开…...

【Ubuntu】常用命令

一般操作 pwd&#xff08;present working directory&#xff09; 显示当前的工作目录/路径。 cd (change directory) 改变目录&#xff0c;用于输入需要前往的路径/目录。 有一些特殊命令也很常用 : 解释 前往同一级的另一个目录 cd ../directory name cd .. 表示进入上…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

计算机系统结构复习-名词解释2

1.定向&#xff1a;在某条指令产生计算结果之前&#xff0c;其他指令并不真正立即需要该计算结果&#xff0c;如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方&#xff0c;那么就可以避免停顿。 2.多级存储层次&#xff1a;由若干个采用不同实现技术的存储…...