02 从QLabel聊起:自定义控件扩展-图片控件-CSDN博客
03 从QLabel聊起:自定义控件扩展-文本控件-CSDN博客
04 自定义Button组件:令人抓狂的QToolButton文本图标居中问题-CSDN博客
目录
开关控件(Switch Control)不在Qt基本组件库里面,但是在我们的日常业务开发中极其常见。
开关控件通常用于在用户界面中表示两种状态(打开和关闭、开和关等),用户可以通过点击或拖动来切换状态。然而, 如果单纯的根据两种状态进行Icon的切换又略显单调些,所以本篇想向大家分享的是具有开关动画效果的Switch按钮组件!
既聊代码也说思路,我们开始今天的动画Swich动画开关组件的分享!
1.为了沿用Qt 按钮组件的基本功能接口,所以我们继承的基类应该选择QAbstractButton而不是QWidget
2.从Swich组件的元素来看,我们可以拆解为三部分逻辑:
综上所述,我们需要用到的模块包括:
- 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;
- }
- void QUiSwitchButton::mouseReleaseEvent(QMouseEvent *pEvt)
- {
- startAnimation();
- QAbstractButton::mouseReleaseEvent(pEvt);
- }
-
- void QUiSwitchButton::handleAnimStateChanged(QVariantAnimation::State curState)
- {
- if (QVariantAnimation::Stopped == curState)
- {
- m_eCurAniType = None;
- }
- update();
- }
-
- void QUiSwitchButton::handleAnimValueChanged(QVariant val)
- {
- m_dCurFrame = val.toDouble();
- update();
- }
-
- void QUiSwitchButton::paintEvent(QPaintEvent *pEvt)
- {
- Q_UNUSED(pEvt);
- QStylePainter paint(this);
- paint.setRenderHints(QPainter::Antialiasing);
- drawBackground(&paint);
- drawHandler(&paint);
- drawText(&paint);
- }
PS:这里要说的是,渲染顺序是有规则的,要根据元素的层级以及依赖顺序来决定
这里要注重点的是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());
- }
这里的重点则是实时计算滑块的中心位置并计算
-
- 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扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦!