06 Qt自绘组件:Switch动画开关组件
系列文章目录
01 Qt自定义风格控件的基本原则-CSDN博客
02 从QLabel聊起:自定义控件扩展-图片控件-CSDN博客
03 从QLabel聊起:自定义控件扩展-文本控件-CSDN博客
04 自定义Button组件:令人抓狂的QToolButton文本图标居中问题-CSDN博客
05 扩展组件:自定义CheckBox组件-CSDN博客
目录
系列文章目录
前言
一、示意效果
二、实现思路
1.概述
2.功能接口举例
3.部分渲染代码
1.动画触发时机
2.响应动画的数值变化以及状态变化
3.根据动画中间差值,渲染背景以及Handle
3.1 渲染Switch背景色
3.2 渲染Swith滑块
总结
前言
开关控件(Switch Control)不在Qt基本组件库里面,但是在我们的日常业务开发中极其常见。
开关控件通常用于在用户界面中表示两种状态(打开和关闭、开和关等),用户可以通过点击或拖动来切换状态。然而, 如果单纯的根据两种状态进行Icon的切换又略显单调些,所以本篇想向大家分享的是具有开关动画效果的Switch按钮组件!
既聊代码也说思路,我们开始今天的动画Swich动画开关组件的分享!
一、示意效果

二、实现思路
1.概述
1.为了沿用Qt 按钮组件的基本功能接口,所以我们继承的基类应该选择QAbstractButton而不是QWidget
2.从Swich组件的元素来看,我们可以拆解为三部分逻辑:
- 圆角矩形背景
- 圆形滑块
- 滑块左右移动的动画
综上所述,我们需要用到的模块包括:
- QPainterPath类:Qt 中用于描述和绘制复杂图形路径的类
- QVariantAnimation:Qt 中用于执行属性动画的类,它可以用于对任意类型的属性进行动画效果的处理
2.功能接口举例
class QUIEXTPLUGIN_EXPORT QUiSwitchButton : public QAbstractButton
{Q_OBJECTenum AnimationType{None= 0, //静态状态下OnAnimation ,//打开动画从左向右滑动OffAnimation, //关闭动画从右向左滑动};
public:QUiSwitchButton(QWidget *parent);~QUiSwitchButton();//设置开状态下文本色void setSwitchOnTextColor(const QColor& clr);//设置关状态下文本色void setSwitchOffTextColor(const QColor& clr);//设置开状态下背景色void setSwitchOnColor(const QColor& clr);//设置关状态下背景色void setSwitchOffColor(const QColor& clr);//设置diasbale颜色void setSwitchDisableColor(const QColor& clr);//设置滑块背景色void setHandleColor(const QColor& clr);
protected:void mouseReleaseEvent(QMouseEvent *pEvt) override;void paintEvent(QPaintEvent *e) override;void drawBackground(QStylePainter*);void drawHandler(QStylePainter*);//void startAnimation();double getCurAnimaValue()const;QColor styledBackgroundColor()const;
protected slots:void handleAnimValueChanged(QVariant val);void handleAnimStateChanged(QVariantAnimation::State);
private:QPointer<QVariantAnimation> m_pAnima;QColor m_clrOnText;QColor m_clrOffText;QColor m_clrOn;QColor m_clrOff;QColor m_clrDisable;QColor m_clrHandler;int m_iHandlerMargin;double m_dCurFrame;AnimationType m_eCurAniType;
}
3.部分渲染代码
1.动画触发时机
void QUiSwitchButton::mouseReleaseEvent(QMouseEvent *pEvt)
{startAnimation();QAbstractButton::mouseReleaseEvent(pEvt);
}
2.响应动画的数值变化以及状态变化
void QUiSwitchButton::handleAnimStateChanged(QVariantAnimation::State curState)
{if (QVariantAnimation::Stopped == curState){m_eCurAniType = None;}update();
}
void QUiSwitchButton::handleAnimValueChanged(QVariant val)
{m_dCurFrame = val.toDouble();update();
}
3.根据动画中间差值,渲染背景以及Handle
void QUiSwitchButton::paintEvent(QPaintEvent *pEvt)
{Q_UNUSED(pEvt);QStylePainter paint(this);paint.setRenderHints(QPainter::Antialiasing);drawBackground(&paint);drawHandler(&paint);drawText(&paint);
}
PS:这里要说的是,渲染顺序是有规则的,要根据元素的层级以及依赖顺序来决定
3.1 渲染Switch背景色
这里要注重点的是QPainterPath的使用以及其渲染规则的不同效果!
void QUiSwitchButton::drawBackground(QStylePainter* paint)
{QRect rcFrame = contentsRect();QRect rcLeft = rcFrame;//左边圆弧QRect rcMiddle = rcFrame;//中间矩形QRect rcRight = rcFrame;//右边圆弧QPainterPath path;path.setFillRule(Qt::WindingFill);//设置填充规则//左rcLeft.setWidth(rcLeft.height());path.addEllipse(rcLeft);//中rcMiddle.adjust(rcLeft.width() / 2, 0, -rcLeft.width() / 2, 0);path.addRect(rcMiddle);//右rcRight.adjust(rcMiddle.width(), 0, 0, 0);path.addEllipse(rcRight);paint->fillPath(path, styledBackgroundColor());
}
3.2 渲染Swith滑块
这里的重点则是实时计算滑块的中心位置并计算
void QUiSwitchButton::drawHandler(QStylePainter* paint)
{//以滑块中心为分界点QRect rcFrame = contentsRect();QRect rcHandler;int iAnimSpan = rcFrame.width() - rcFrame.height();QPoint ptCenter(rcFrame.width() - rcFrame.height() / 2 - iAnimSpan * (1.0 - getCurAnimaValue()), rcFrame.height() / 2);rcHandler = QRect(ptCenter.x() - rcFrame.height() / 2, 0, rcFrame.height(), rcFrame.height());rcHandler = rcHandler.marginsRemoved(QMargins(m_iHandlerMargin, m_iHandlerMargin, m_iHandlerMargin, m_iHandlerMargin));QPainterPath path;path.addEllipse(rcHandler);paint->fillPath(path, m_clrHandler);
}
总结
以上就是今天要分享的:Qt如何自绘 Switch开关动画按钮的内容!
既聊思路,也说代码!我们下次继续分享自定义风格扩展组件!
PS:本专栏所有篇幅涉及的UI扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦!
相关文章:
06 Qt自绘组件:Switch动画开关组件
系列文章目录 01 Qt自定义风格控件的基本原则-CSDN博客 02 从QLabel聊起:自定义控件扩展-图片控件-CSDN博客 03 从QLabel聊起:自定义控件扩展-文本控件-CSDN博客 04 自定义Button组件:令人抓狂的QToolButton文本图标居中问题-CSDN博客 0…...
大语言模型LLM分布式训练:大规模数据集上的并行技术全景探索(LLM系列03)
文章目录 大语言模型LLM分布式训练:大规模数据集上的并行技术全景探索(LLM系列03)1. 引言1.1 大语言模型(LLM)的重要性及其规模化挑战1.2 分布式训练策略的需求 2. 分布式训练基础原理2.1 并行计算的基本概念与分类 3.…...
98.验证二叉搜索树
98.验证二叉搜索树 思路 1.一开始使用递归,想当前节点满足条件后,再使左右子树分别满足条件。失败,只考虑了节点与左右子树的大小,未考虑隔代节点的关系。 2.转变思路,使用中序遍历的方法,从第一个节点开…...
2月21日,每日信息差
🎖 素材来源官方媒体/网络新闻 🎄 10 家央企签订倡议书:将主动向社会开放人工智能应用场景 🌍 上海成为首个固定资产投资破万亿的一线城市 🌋 特斯拉扩建德国工厂的计划遭当地居民反对 🎁 加拿大公司利用木…...
android.text.BoringLayout.isBoring 的 NullPointerException
都是重写TextView.settext()函数导致的坑~ override fun setText(text: CharSequence?, type: BufferType?) {if (text.isNullOrEmpty()) {return}//业务代码super.setText(text, type)} java.lang.NullPointerException at android.text.BoringLayout.isBoring(BoringLayo…...
C++ 高频考点
1. C/C内存有哪几种类型? C中,内存分为5个区:堆(malloc)、栈(如局部变量、函数参数)、程序代码区(存放二进制代码)、全局/静态存储区(全局变量、static变量)和常量存储区(常量&…...
Ubuntu安装SVN服务并结合内网穿透实现公网访问本地存储文件
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svns…...
2月20日,每日信息差
第一、中国联通 1 月智慧客服客户问题解决率为 97.9%,大联接用户达 10.02 亿户,5G 套餐用户约 2.64 亿户,物联网终端连接约 5.06 亿户。5G 行业虚拟专网服务客户数为 9185 个,智慧客服问题解决率 97.9%,智能服务占比 8…...
Visual Studio清单作用
1、作用: 制定程序依赖的C运行库的dll及版本,包括mfc,atl,crt等,在Visual Studio安装目录下的vc/redist下有debug和release版本 2、确定应用程序依赖哪些visual C 库方法: 查看项目-》项目设置-》常规&…...
Java中的==和equals()方法的区别是?hashCode()和equals()的关系是什么?
目录 解释Java中的和equals()方法。 hashCode()和equals()的关系是什么? 解释Java中的和equals()方法。 在Java中,和equals()方法都用于比较两个对象,但它们在比较时的侧重点和行为上有所不同。 1. **运算符:** - 是Java中的…...
yaml-cpp开源库使用
源码下载:https://github.com/jbeder/yaml-cpp 1.yaml-cpp编译 步骤主要如下:进入源码目录后 mkdir build cd build cmake … make make install 2.代码示例 #include "funset.hpp" #include <string> #include <fstream> #i…...
【C++私房菜】序列式容器的迭代器失效问题
目录 一、list的迭代器失效 二、vector的迭代器失效 1、空间缩小操作 2、空间扩大操作 三、总结 在C中,当对容器进行插入或删除操作时,可能会导致迭代器失效的问题。所谓迭代器失效指的是,原先指向容器中某个元素的迭代器,在…...
MySQL 篇-深入了解 DML、DQL 语言(二)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 DML、DQL 语言说明 2.0 使用 DML 实现对数据管理和操作 2.1 DML - 增添数据 insert 2.2 DML - 修改数据 update 2.3 DML - 删除数据 delete 3.0 使用 DQL 实现对…...
端智能:面向手机计算环境的端云协同AI技术创新
近年来,随着移动端设备软硬件能力的进步,移动端的算力有了很大提升,同时面向移动端的机器学习框架和模型轻量化技术越来越成熟,端上的AI能力逐渐进入大众视野,端智能在电商领域也开始逐步走向规模化应用。通过持续探索…...
PHP函数 “password_hash“ 哈希密码
哈希函数是一种将输入转换为固定长度字符串的方法,这个过程是不可逆的,也就是无法从哈希值还原出原始输入。通过将密码进行哈希处理,即使数据库泄露,攻击者也无法简单地获取到用户密码。 在PHP中,我们可以使用 "…...
第十一天-Excel的操作
目录 1.xlrd-Excel的读模块 安装 使用 获取工作簿 读取工作簿的内容 xlsxwriter-Excel的写模块 安装 使用 生成图表 add_series参数 图表的样式 demo:生成图表 Excel的操作在python中有多个模块,为了能够快速使用,选择了相对简单…...
【java任意文件漏洞修复,使用文件魔数解决】
java任意文件漏洞修复,使用文件魔数解决 背景: 客户进行渗透测试,验证上传文件的程序没有对上传文件作任何过滤,导致可以上传任意文件到服务器,甚至是病毒文件和Webshell木马文件。 解决办法:对于上传的附件…...
LeetCode 热题 100 | 二叉树(二)
目录 1 543. 二叉树的直径 2 102. 二叉树的层序遍历 3 108. 将有序数组转换为二叉搜索树 菜鸟做题,语言是 C 1 543. 二叉树的直径 这道题和 124. 二叉树中的最大路径和 太像了 题眼:二叉树的 直径 是指树中任意两个节点之间 最长路径的长度 。…...
mini-spring|定义标记类型Aware接口,实现感知容器对象
**前言:**如果我们想获得 Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader等这些能力做一些扩展框架的使用时该怎么操作呢。所以我们本章节希望在 Spring 框架中提供一种能感知容器操作的接口,如果谁实现了这样的一个接口ÿ…...
83. 删除排序链表中的重复元素
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 输入:head = [1,1,2] 输出:[1,2] 输入:head = [1,1,2,3,3] 输出:[1,2,3] 提示: 链表中节点数目在范围 [0, 300] 内-100 <= Node.val <= 100题目数据保证链表已…...
FastAPI 项目 PyInstaller 打包 exe 全踩坑根治教程(Windows 全电脑通用分发)
文章前言本文基于FastAPISQLite 本地数据库项目,完整讲解如何将 Python 后端项目打包为独立 exe 可执行文件,实现任意 Windows 电脑无需安装 Python、无需配置环境、双击直接运行。全程收录打包过程中所有经典报错:isatty终端日志崩溃、WinEr…...
Windows卸载工具横向对比:极客卸载为何能脱颖而出
Windows平台的软件卸载需求催生了众多卸载工具。 面对琳琅满目的选择,用户往往难以判断哪款工具最适合自己。 本文将从多个维度对比极客卸载与其他主流方案,为读者提供客观的选择参考。 Windows系统自带的程序卸载功能是最基础的解决方案。 它通过调用软…...
【量化实战】解码期权PCR:从情绪指标到稳健策略的构建与优化
1. 期权PCR指标的本质与市场情绪解码 第一次接触期权PCR指标时,我和大多数新手一样困惑——这个看似简单的比值背后,到底藏着什么市场秘密?经过多年实战,我发现它就像市场的"心电图",能实时反映投资者的集体…...
StarUML插件DDL实战:5分钟搞定ER图到MySQL建表脚本(含Java代码生成)
StarUML插件DDL实战:5分钟搞定ER图到MySQL建表脚本(含Java代码生成) 在数据库设计领域,效率往往决定着项目推进的速度。想象一下这样的场景:产品经理刚刚确认完需求,开发团队需要在两小时内完成数据库设计并…...
告别黑屏!手把手教你用UEFI VFR语法定制自己的BIOS Setup界面(附完整代码示例)
从零构建UEFI BIOS设置界面:VFR语法实战指南 在嵌入式开发和定制硬件领域,能够自主设计BIOS设置界面是一项极具价值的能力。想象一下,当你需要为一款工业控制主板或服务器定制专属的启动配置选项时,传统的黑屏BIOS界面往往无法满足…...
Fish Speech 1.5企业实操:为内部知识库添加多语种语音检索功能
Fish Speech 1.5企业实操:为内部知识库添加多语种语音检索功能 1. 引言:当知识库会“说话” 想象一下,你的团队里有一位精通十几种语言的同事,他能把任何文档、报告、代码注释,用清晰、自然的语音读出来。无论是中文…...
别再让你的Elasticsearch裸奔了!手把手教你配置安全认证(附一键检测脚本)
Elasticsearch安全加固实战:从漏洞应急到生产级防护 那天凌晨三点,我被一阵急促的电话铃声惊醒。电话那头是值班同事颤抖的声音:"我们的用户数据被挂在暗网论坛了,黑客留下的日志显示是通过Elasticsearch未授权访问漏洞获取…...
S32K144时钟配置避坑指南:手把手教你用S32DS的clock_manager组件搞定外设时钟(附代码)
S32K144时钟配置实战:从原理到避坑的完整指南 第一次接触S32K144的时钟系统时,我被它的灵活性震惊了——但随之而来的是配置时的迷茫。记得有一次调试FlexCAN模块,程序莫名其妙地进入复位中断循环,花了整整两天才发现是时钟门控没…...
从晶振到基站同步:拆解手机射频校准中AFC的‘隐藏’逻辑与避坑指南
从晶振到基站同步:拆解手机射频校准中AFC的‘隐藏’逻辑与避坑指南 在智能手机的射频系统中,频率校准(AFC)就像一位隐形的交响乐指挥,默默协调着晶振、基带芯片与基站之间的精密互动。当你在电梯里流畅刷短视频时&…...
OpenCV形态学操作进阶:手把手教你用getStructuringElement自定义核,玩转腐蚀膨胀
OpenCV形态学操作进阶:手把手教你用getStructuringElement自定义核,玩转腐蚀膨胀 在图像处理领域,形态学操作就像是一把精密的雕刻刀,能够帮助我们精确地塑造和优化图像特征。而getStructuringElement函数则是这把雕刻刀的核心调节…...
