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

2024-02-24 11:52

本文主要是介绍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动画开关组件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/742022

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Qt spdlog日志模块的使用详解

《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧... 目录版本摘要例子logmanager.cpp文件main.cpp文件版本spdlog版本:1.5.0采用1.5.0版本主要

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方