06 Qt自绘组件:Switch动画开关组件
温馨提示:这篇文章已超过393天没有更新,请注意相关的内容是否还可用!
系列文章目录
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 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扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦!

