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

2024-02-29 1205阅读

温馨提示:这篇文章已超过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动画开关组件的分享!


一、示意效果

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

二、实现思路

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

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]