06 Qt自绘组件:Switch动画开关组件

news2024/11/19 15:11:21

系列文章目录

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_OBJECT
    enum 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扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1475693.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ISP代理是什么?跨境账号养号为什么要选择它?

在跨境出海业务中&#xff0c;代理IP对于您的在线任务至关重要&#xff0c;尤其是对于那些运行多个帐户的人来说。为您的帐户选择正确类型的代理对于确保帐户安全非常重要&#xff0c;劣质的IP容易使账号遭受封号风险。IPFoxy的多种代理IP类型应用范围各有侧重&#xff0c;其中…

如何在aws服务器上部署mysql

在AWS服务器上部署 MySQL 数据库可以通过以下步骤完成&#xff1a; 启动 EC2 实例&#xff1a; 在 AWS 控制台中启动一个 EC2 实例&#xff0c;选择适合你需求的实例类型和配置。 安全组配置&#xff1a; 确保你的 EC2 实例的安全组配置允许来自你的 IP 地址的 MySQL 连接。默…

12. WorkQueue(工作队列)

WorkQueue WorkQueue 称为工作队列&#xff0c;Kubernetes 的 WorkQueue 队列与普通 FIFO&#xff08;先进先出&#xff0c;First-In&#xff0c;First-Out&#xff09;队列相比&#xff0c;实现略显复杂&#xff0c;它的主要功能在于标记和去重&#xff0c;并支持如下特性。 …

linux系统Jenkins的安装

Jenkins安装 安装上传安装包解压包首次登录要去服务器查看密码&#xff0c;更改密码选择需要安装的插件设置Admin用户和密码安装完成 安装 上传安装包 上传 jdk17 tomcat jenkins.war的安装包 . 上传 tomcat安装包解压包 解压jdk tar xf jdk-11.0.18_linux-x64_bin.tar.gz解…

雾锁王国Enshrouded服务器CPU内存配置怎么选择?

雾锁王国/Enshrouded服务器CPU内存配置如何选择&#xff1f;阿里云服务器网aliyunfuwuqi.com建议选择8核32G配置&#xff0c;支持4人玩家畅玩&#xff0c;自带10M公网带宽&#xff0c;1个月90元&#xff0c;3个月271元&#xff0c;幻兽帕鲁服务器申请页面 https://t.aliyun.com…

【HarmonyOS】鸿蒙开发之Video组件——第3.7章

Video组件内VideoOptions属性简介 src&#xff1a;设置视频地址。currentProgressRate&#xff1a;设置视频播放倍速&#xff0c;参数说明如下&#xff1a; number|string&#xff1a;只支持 0.75 &#xff0c; 1.0 &#xff0c; 1.25 &#xff0c; 1.75 &#xff0c; 2.0 。P…

首超星巴克,瑞幸咖啡开始“守擂”?

农历新年开年短短半个月&#xff0c;瑞幸咖啡凭一己之力&#xff0c;似乎拉开了国内现磨咖啡行业竞争的新序幕。 先是新年开工首日&#xff0c;瑞幸咖啡每周“9.9元喝一杯”的可选性品类减少&#xff0c;登上微博热搜&#xff0c;引发市场对于现磨咖啡行业生态的可持续性担忧。…

[计算机网络]--MAC/ARP/DNS协议

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、认识以…

ARM系列 -- 虚拟化(五)

在ARM体系结构中&#xff0c;处理器内部有通用计时器&#xff0c;通用计时器包含一组比较器&#xff0c;用来与系统计数器进行比较&#xff0c;一旦通用计时器的值小于等于系统计数器时便会产生时钟中断。 大家看到这里是不是想起了前面讲GIC时提到的PPI&#xff08;private p…

招聘系统架构的设计与实现

在当今竞争激烈的人才市场中&#xff0c;有效的招聘系统对企业吸引、筛选和管理人才至关重要。本文将探讨招聘系统的架构设计与实现&#xff0c;帮助企业构建一个高效、可靠的人才招聘平台。 ## 1. 系统架构设计 ### 1.1 微服务架构 招聘系统通常采用微服务架构&#xff0c;将…

移动Web系统中无监督KPI异常检测的监督式微调

简介 本文介绍由清华大学、南开大学、中国移动研究院与必示科技共同合作的论文&#xff1a;移动Web系统中无监督KPI异常检测的监督式微调。该论文已被The Web Conference 2024&#xff08;International World Wide Web Conference&#xff09;会议录用&#xff0c;论文标题为&…

【Hudi】核心概念

https://www.bilibili.com/video/BV1ue4y1i7na?p17&vd_sourcefa36a95b3c3fa4f32dd400f8cabddeaf 大数据新风口&#xff1a;Hudi数据湖&#xff08;尚硅谷&Apache Hudi联合出品&#xff09; 1 基础概念 1.1 时间轴(TimeLine) 1.2 文件布局(File Layout) 1.3 索引(In…

Leetcode—82. 删除排序链表中的重复元素 II【中等】

2024每日刷题&#xff08;117&#xff09; Leetcode—82. 删除排序链表中的重复元素 II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val…

npm login报错 ‘proxy‘ config is set properly. See: ‘npm help config‘

报错提示 解决办法 按照以下的顺序执行命令行 检查自己的代理 npm config get proxy npm config get npm config get https-proxy npm config get registry代理和缓存置空并且设置新镜像 npm config set proxy null npm config set https-proxy null npm config set regist…

面试笔记系列七之多线程+分布式系统基础知识点整理及常见面试题

介绍一下线程的生命周期及状态&#xff1f; 1.创建 当程序使用new关键字创建了一个线程之后&#xff0c;该线程就处于一个新建状态&#xff08;初始状态&#xff09;&#xff0c;此时它和其他Java对象一样&#xff0c;仅仅由Java虚拟机为其分配了内存&#xff0c;并初始化了其成…

【Linux】jieba的安装和使用

目录 链接 jieba库简介 ​获得jieba库 怎么使用jieba库 链接 因为github下载东西的时间原因&#xff0c;下面这个网站会定期将jieba从github镜像回来 项目 探索 GitCodehttps://gitcode.net/explore输入cppjieba进行搜索&#xff0c;点击相应链接进入 jieba库简介 需要…

【前端知识点】

虚拟 dom&#xff1a; 虚拟 dom 就是 vue 通过 js 对象渲染虚拟 dom 的&#xff0c;虚拟 dom 的 js 对象包含节点的类型、属性、子节点等信息&#xff0c;这些虚拟 dom 节点会构成一棵树形结构&#xff0c;用来表示整个页面的结构。 当 vue 组件更新时&#xff0c;会通过 diff…

雾锁王国服务器怎么建?雾锁王国服务器搭建方法

雾锁王国Enshrouded服务器搭建怎么搭建&#xff1f;非常简单&#xff0c;阿里云计算巢雾锁王国程序&#xff0c;可以一键搭建雾锁王国多人联机服务器&#xff0c;腾讯云是基于雾锁王国镜像系统&#xff0c;阿里云服务网aliyunfuwuqi.com汇总雾锁王国服务器搭建&#xff0c;超简…

Python爬虫实战第二例【二】

零.前言&#xff1a; 本文章借鉴&#xff1a;Python爬虫实战&#xff08;五&#xff09;&#xff1a;根据关键字爬取某度图片批量下载到本地&#xff08;附上完整源码&#xff09;_python爬虫下载图片-CSDN博客 大佬的文章里面有API的获取&#xff0c;在这里我就不赘述了。 一…