[Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

1、功能介绍

在项目UI中使用较多的打开/关闭的开关按钮,一般都是找图片去做效果,比如说如下的图像来表征打开或关闭。

图一.png图二.png图三.PNG

如果想要控件有打开/关闭的动画效果或比较好的视觉效果,这里就可以使用自定义控件,使用Painter来绘制控件。软件最终的效果如上图三:

2、主要的实现绘制代码

绘制背景区域

void SwitchButton::drawBackGround(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;if (isEnabled()) {bgColor.setAlpha(140);}painter->setBrush(bgColor);QRect rect(0, 0, width(), height());int side = qMin(width(), height());//左侧半圆QPainterPath path1;path1.addEllipse(rect.x(), rect.y(), side, side);//右侧半圆QPainterPath path2;path2.addEllipse(rect.width() - side, rect.y(), side, side);//中间的矩形QPainterPath path3;path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, height());QPainterPath path = path1 + path2 + path3;painter->drawPath(path);//绘制文本//滑块半径int sliderWidth = qMin(height(), width()) - m_space * 2 - 5;if (m_checked){QRect textRect(0, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOn);} else {QRect textRect(sliderWidth, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOff);}painter->restore();
}

绘制滑块

void SwitchButton::drawSlider(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor color = m_checked ? m_sliderColorOn : m_sliderColorOff;painter->setBrush(QBrush(color));int sliderWidth = qMin(width(), height()) - m_space * 2;QRect rect(m_space + m_startX, m_space, sliderWidth, sliderWidth);painter->drawEllipse(rect);painter->restore();
}

这里引入了滑块动画效果,设定一个定时器,根据滑块的距离设置一个动画的效果

    m_timer = new QTimer(this);m_timer->setInterval(30);connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateValue()));void SwitchButton::UpdateValue()
{if (m_checked) {if (m_startX < m_endX) {m_startX += m_step;} else {m_startX = m_endX;m_timer->stop();}} else {if (m_startX > m_endX) {m_startX -= m_step;} else {m_startX = m_endX;m_timer->stop();}}update();
}

3、功能实现源码

switchButton.h

#ifndef SWITCHBUTTON_H
#define SWITCHBUTTON_H#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QColor>class SwitchButton : public QWidget
{Q_OBJECT
public:explicit SwitchButton(QWidget *parent = nullptr);signals:void statusChanged(bool checked);public slots:private slots:void UpdateValue();private:void drawBackGround(QPainter *painter);void drawSlider(QPainter *painter);protected:void paintEvent(QPaintEvent *event);void mousePressEvent(QMouseEvent *event);private://滑块距离边界距离int m_space;//圆角角度int m_radius;//是否选中bool m_checked;//是否显示文本bool m_showText;//是否显示圆bool m_showCircle;//是否使用动画bool m_animation;//打开时候背景色QColor m_bgColorOn;//关闭时候背景色QColor m_bgColorOff;//打开时候滑块颜色QColor m_sliderColorOn;//关闭时候滑块颜色QColor m_sliderColorOff;//文字颜色QColor m_textColor;//打开时候文字QString m_textOn;//关闭时候文字QString m_textOff;//动画定时器QTimer *m_timer;//动画步长int m_step;//滑块开始X轴坐标int m_startX;//滑块介绍X轴坐标int m_endX;public:int space()                 const;int radius()                const;bool checked()              const;bool showText()             const;bool showCircle()           const;bool animation()            const;QColor bgColorOn()          const;QColor bgColorOff()         const;QColor sliderColorOn()      const;QColor sliderColorOff()     const;QColor textColor()          const;QString textOn()            const;QString textOff()           const;int step()                  const;int startX()                const;int endX()                  const;public Q_SLOTS:void setSpace(int space);void setRadius(int radius);void setChecked(bool checked);void setShowText(bool show);void setShowCircle(bool show);void setAnimation(bool ok);void setBgColorOn(const QColor &color);void setBgColorOff(const QColor &color);void setSliderColorOn(const QColor &color);void setSliderColorOff(const QColor &color);void setTextColor(const QColor &color);void setTextOn(const QString &text);void setTextOff(const QString &text);//    void setStep(int step);
//    void setStartX(int startX);
//    void setEndX(int endX);
};#endif // SWITCHBUTTON_H

switchButton.cpp

#pragma execution_character_set("utf-8")
#include "SwitchButton.h"
#include <QPainter>SwitchButton::SwitchButton(QWidget *parent) : QWidget(parent)
{m_space = 2;m_radius = 5;m_checked = false;m_showText = true;m_showText = false;m_animation = true;m_bgColorOn = QColor(21, 156, 119);m_bgColorOff = QColor(111, 122, 126);m_sliderColorOn = QColor(255, 255, 255);m_sliderColorOff = QColor(255, 255, 255);m_textColor = QColor(255, 255, 255);m_textOn = "开启";m_textOff = "关闭";m_step = 0;m_startX = 0;m_endX = 0;m_timer = new QTimer(this);m_timer->setInterval(30);connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateValue()));
}void SwitchButton::drawBackGround(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;if (isEnabled()) {bgColor.setAlpha(140);}painter->setBrush(bgColor);QRect rect(0, 0, width(), height());int side = qMin(width(), height());//左侧半圆QPainterPath path1;path1.addEllipse(rect.x(), rect.y(), side, side);//右侧半圆QPainterPath path2;path2.addEllipse(rect.width() - side, rect.y(), side, side);//中间的矩形QPainterPath path3;path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, height());QPainterPath path = path1 + path2 + path3;painter->drawPath(path);//绘制文本//滑块半径int sliderWidth = qMin(height(), width()) - m_space * 2 - 5;if (m_checked){QRect textRect(0, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOn);} else {QRect textRect(sliderWidth, 0, width() - sliderWidth, height());painter->setPen(QPen(m_textColor));painter->drawText(textRect, Qt::AlignCenter, m_textOff);}painter->restore();
}void SwitchButton::drawSlider(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);QColor color = m_checked ? m_sliderColorOn : m_sliderColorOff;painter->setBrush(QBrush(color));int sliderWidth = qMin(width(), height()) - m_space * 2;QRect rect(m_space + m_startX, m_space, sliderWidth, sliderWidth);painter->drawEllipse(rect);painter->restore();
}void SwitchButton::paintEvent(QPaintEvent *ev)
{//启用反锯齿QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);//绘制背景drawBackGround(&painter);//绘制滑块drawSlider(&painter);
}void SwitchButton::mousePressEvent(QMouseEvent *ev)
{Q_UNUSED(ev)m_checked = !m_checked;emit statusChanged(m_checked);//计算步长m_step = width() / 10;//计算滑块X轴终点坐标if (m_checked) {m_endX = width() - height();} else {m_endX = 0;}//判断是否使用动画if (m_animation) {m_timer->start();} else{m_startX = m_endX;update();}
}void SwitchButton::UpdateValue()
{if (m_checked) {if (m_startX < m_endX) {m_startX += m_step;} else {m_startX = m_endX;m_timer->stop();}} else {if (m_startX > m_endX) {m_startX -= m_step;} else {m_startX = m_endX;m_timer->stop();}}update();
}int SwitchButton::space() const
{return m_space;
}int SwitchButton::radius() const
{return m_radius;
}bool SwitchButton::checked() const
{return m_checked;
}bool SwitchButton::showText() const
{return m_showText;
}bool SwitchButton::showCircle() const
{return m_showCircle;
}bool SwitchButton::animation() const
{return m_animation;
}QColor SwitchButton::bgColorOn() const
{return m_bgColorOn;
}QColor SwitchButton::bgColorOff() const
{return m_bgColorOff;
}QColor SwitchButton::sliderColorOn() const
{return m_sliderColorOn;
}QColor SwitchButton::sliderColorOff() const
{return m_sliderColorOff;
}QColor SwitchButton::textColor() const
{return m_textColor;
}QString SwitchButton::textOn() const
{return m_textOn;
}QString SwitchButton::textOff() const
{return m_textOff;
}int SwitchButton::step() const
{return m_step;
}int SwitchButton::startX() const
{return m_startX;
}int SwitchButton::endX() const
{return m_endX;
}void SwitchButton::setSpace(int space)
{if (m_space != space) {m_space = space;update();}
}void SwitchButton::setRadius(int radius)
{if (m_radius != radius) {m_radius = radius;update();}
}void SwitchButton::setChecked(bool checked)
{if (m_checked != checked) {m_checked = checked;update();}
}void SwitchButton::setShowText(bool show)
{if (m_showText != show) {m_showText = show;update();}
}void SwitchButton::setShowCircle(bool show)
{if (m_showCircle != show) {m_showCircle = show;update();}
}void SwitchButton::setAnimation(bool ok)
{if (m_animation != ok) {m_animation = ok;update();}
}void SwitchButton::setBgColorOn(const QColor &color)
{if (m_bgColorOn != color) {m_bgColorOn = color;update();}
}void SwitchButton::setBgColorOff(const QColor &color)
{if (m_bgColorOff != color) {m_bgColorOff = color;update();}
}void SwitchButton::setSliderColorOn(const QColor &color)
{if (m_sliderColorOn != color) {m_sliderColorOn = color;update();}
}void SwitchButton::setSliderColorOff(const QColor &color)
{if (m_sliderColorOff != color) {m_sliderColorOff = color;update();}
}void SwitchButton::setTextColor(const QColor &color)
{if (m_textColor != color) {m_textColor = color;update();}
}void SwitchButton::setTextOn(const QString &text)
{if (m_textOn != text) {m_textOn = text;update();}
}void SwitchButton::setTextOff(const QString &text)
{if (m_textOff != text) {m_textOff = text;update();}
}//void SwitchButton::setStep(int step)
//{
//    if (m_step != step) {
//        m_step = step;
//        update();
//    }
//}//void SwitchButton::setStartX(int startX)
//{//}//void SwitchButton::setEndX(int endX)
//{//}

4、效果与源码

控件实现的动态效果如下
控件效果
本小例程的代码放到我的开源gitte项目里,欢迎一起学习,也希望能收获你的小星星。
源码SwitchButton

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

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

相关文章

JavaScript的学习笔记

<script src"index.js" defer></script>&#xff0c;defer的作用是延迟加载index.js文件 定义变量 变量的类型分为两大类&#xff1a;基本类型和复合类型 JavaScript是一种弱类型语言&#xff0c;所以没有强类型语言所具有的int,float,char等等&#x…

阿里云linux服务器数据盘待初始化

如果您的阿里云Linux服务器数据盘已经购买但未进行初始化和格式化&#xff0c;您可以按照以下步骤进行操作&#xff1a; 查看数据盘信息&#xff1a; 使用fdisk -l命令查看当前所有磁盘的信息&#xff0c;识别未初始化的数据盘设备名称&#xff0c;如/dev/xvdb。分区数据盘&am…

Spring 实现 OAuth2 授权之解决方案

Spring Security OAuth2 - 已经废弃的项目 早期的Spring 使用 Spring Security OAuth2 实现 OAuth 2.0 的认证服务器和资源服务器。OAuth2是一个授权框架,它允许第三方应用获取有限的访问权限,而无需获取用户的账号和密码等敏感信息。通过这种方式,OAuth2协议实现了安全的用…

java语言实现树莓派4b下的超远程高精度电子秤

通常情况下,Java语言基于jvm虚拟机,垃圾回收,代码优化等机制,无法直接通过Java语言来操控硬件,获取传感器数据,本文做个折中,通过编写c语言代码,编译为.so文件,Java使用jni调用.so文件的方式,springboot操作Java方法,来编写一套超远程高精度电子秤的代码。总成本:2…

VScode通过ssh连接github

通过ssh连接github 1.生成公钥和私钥2.设置config文件3.配置ssh免密登录4.远程仓库初始化 1.生成公钥和私钥 首先选择一个文件夹&#xff0c;右击 git bash here&#xff0c;在命令行输入命令&#xff0c;按下三次回车生成一个**.ssh文件夹**&#xff0c;一般在用户的user根目…

AI浪潮下,新闻媒体的新变革与记者职业的未来发展

中国媒体经历了从口口相传到报纸、再到电视&#xff0c;最后到互联网自媒体的演变过程。传统报业在新媒体冲击下面临着存亡的挑战。 中国媒体的演变概括如下&#xff1a; 19世纪初&#xff1a;主要依靠口口相传和阅读报纸获取信息&#xff1b;20世纪&#xff1a;电视逐渐取代报…

MyBatis:查询与连接池

一、查询 1、多表查询 尽量避免使用多表查询&#xff0c;尤其是对性能要求较高的项目。因为多表查询必然会导致性能变低。 例如&#xff1a;select *from ta运行需要10ms&#xff0c;select *from tb 运行也需要10s。但是&#xff0c;select *from ta left join tb on ta.xx…

zabbix监控vmware esxi

一、zabbix服务端配置 修改zabbix_server.conf配置文件 vim /etc/zabbix/zabbix_server.conf #######zabbix_server.conf底部第二行开始添加下面配置######## StartVMwareCollectors5 #StartVMwareCollectors - 预先启动Vmware collector收集器实例的数量。此值取决于要监控的…

android13实现切换导航模式功能

支持android13以上系统&#xff0c;需要系统签名。 public class NavigationHelper {/*** 设置导航模式** param context* param mode GESTURAL&#xff1a;手势 TWOBUTTON&#xff1a;二按钮 THREEBUTTON&#xff1a;三按钮*/public static void setNavigationMode(Contex…

GEE显示研究区sentinel-2每年可用影像

第一次使用GEE&#xff0c;用了别人的代码&#xff0c;想查看每年影像可用数量&#xff0c;但是老是报错&#xff0c;说是null geometry&#xff0c;之前我是用GAMMA软件导出的kml文件&#xff0c;后面在arcgis自己勾画了sho文件&#xff0c;线类型&#xff0c;然后我就在想会不…

android各种软件下载

Android Studio 历史版本下载地址&#xff1a;https://developer.android.google.cn/studio/archive 拉到网页底部&#xff0c;点击 I agree to the terms 按钮 buildTools历史版本下载地址&#xff1a;https://androidsdkmanager.azurewebsites.net/build_tools.html

MySQL进阶-----索引的结构与分类

目录 前言 一、认识索引 二、索引结构 1.概述 2. 二叉树 3 .B-Tree 4.BTree 5.Hash 三、索引的分类 1 .索引分类 2 .聚集索引&二级索引 前言 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统还维…

进制转换(Python)

一、把10进制数转换成N进制数 将10进制数转换为N进制数通常遵循以下步骤&#xff1a; 将10进制数除以N&#xff0c;记录下商和余数。将商作为新的被除数重复步骤1&#xff0c;直到商为0。将得到的余数逆序排列&#xff0c;这就是所求的N进制数。 假设我们要将10进制数29转换为N…

【第十二届“泰迪杯”数据挖掘挑战赛】【2024泰迪杯】B题基于多模态特征融合的图像文本检索—解题全流程(持续更新)

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛B题 解题全流程&#xff08;持续更新&#xff09; -----基于多模态特征融合的图像文本检索 一、写在前面&#xff1a; ​ 本题的全部资料打包为“全家桶”&#xff0c; “全家桶”包含&#xff1a;模型数据、全套代码、训练好的模…

OpenLayers基础教程——使用WebGLPoints加载海量点数据

1、前言 最近遇到一个问题&#xff1a;如何在OpenLayers中高效加载海量的场强点&#xff1f;由于项目中的一些要求&#xff0c;不能使用聚合的方法加载。一番搜索之后发现&#xff1a;OpenLayers中有一个WebGLPoints类&#xff0c;使用该类可以轻松应对几十万的数据量&#xf…

汽车后视镜反射率检测光纤光谱仪:安全驾驶的守护神

在汽车的日常使用中&#xff0c;后视镜扮演着至关重要的角色。它不仅帮助驾驶员观察车辆后方的情况&#xff0c;还确保了行车的安全性。然而&#xff0c;由于各种原因&#xff0c;后视镜的反射率可能会降低&#xff0c;从而影响到驾驶员的视线范围和判断能力。为了解决这一问题…

7-Zip、7z、7za.exe 命令行用法(加解压zip文件)

文章目录 7-Zip什么是7z使用7-Zip、7z的场景 常用命令7za.exe 命令行用法 7-Zip 什么是7z 主页&#xff1a;http://www.7-zip.org/ 7z&#xff0c;全称7-Zip&#xff0c; 是一款开源软件。是目前公认的压缩比例最大的压缩解压软件。 7-Zip is free software with open sour…

windows允许指定IP段访问本地端口

虚拟机内部应用有时候需要访问windows的一些端口&#xff0c;例如数据库或Redis等&#xff0c;默认情况下&#xff0c;需关闭windows上的防火墙才可正常访问。本文通过在防火墙设置允许指定IP段进行访问来处理&#xff0c;不用每次操作都关闭防火墙。 入站规则-》新建规则 完成…

ASR工业化语音模型总结

1、wenet模型&#xff1a;WeNet语音识别实战-CSDN博客 git地址&#xff1a;GitHub - wenet-e2e/wenet: Production First and Production Ready End-to-End Speech Recognition Toolkit 生产应用方式为:使用pytorch训练&#xff0c;使用c部署。

日常总结:出现报错信息

上述代码报如下错误FATAL EXCEPTION: main Process: com.ear.myapplication, PID: 2173 java.lang.RuntimeException: com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "2024-02-26 13:55:38"at com.ear.ams.ui.funct…