QT纯代码实现滑动开关控件

        开关按钮大家应该很熟悉,在设置里面经常遇到,切换时候的滑动效果比较帅气。通常说的开关按钮,有两个状态:on、off。大部分的开关按钮控件,基本上有两大类,第一类是纯代码绘制,这种对代码的掌控度要求比较高,但是灵活性比较好。第二类是贴图,专业的美工做好的各种状态的背景图片,只需要用代码将该图片画到界面上即可。下面,介绍一种实现纯代码绘制的开关按钮。想看利用贴图来实现的开关按钮请移步:https://blog.csdn.net/u012959478/article/details/140423375

一、简述

         QT纯代码实现滑动开关控件。

二、 设计思路

        通过继承QAbstractButton类,重写paintEvent函数来自定义绘制过程。        

        首先我们将滑动进度条的整体进行分块,先剖析整个按钮的实现包括的元素,分为两个外圆、一个矩形、一个内圆(白色)组成。接着我们通过QPaintEvent绘制出按钮的静止状态下的界面形状。接着,我们再剖析进度条的动态过程其动态过程为圆心在不同的时刻处在按钮中的不同位置。通过QPropertyAnimation来设置从左向右的运动实现滑动过程。

三、效果 

四、核心代码  
1、头文件
#ifndef SLIPBUTTON_H
#define SLIPBUTTON_H#include <QAbstractButton>struct SlipButtonPrivate;
class SlipButton : public QAbstractButton
{Q_OBJECTQ_PROPERTY(int offset READ offset WRITE setOffset)Q_PROPERTY(QColor checkedBackgroundColor READ checkedBackgroundColor WRITE setCheckedBackgroundColor)Q_PROPERTY(QColor uncheckedBackgroundColor READ uncheckedBackgroundColor WRITE setUncheckedBackgroundColor)
public:explicit SlipButton(QWidget* parent = nullptr);~SlipButton() override;QSize sizeHint() const override;QSize minimumSizeHint() const override;public slots:void setCheckedBackgroundColor(const QColor &color);QColor checkedBackgroundColor() const;void setUncheckedBackgroundColor(const QColor &color);QColor uncheckedBackgroundColor() const;protected:void paintEvent(QPaintEvent* event) override;void enterEvent(QEvent *event) override;void leaveEvent(QEvent* event) override;void resizeEvent(QResizeEvent* event) override;private slots:void onStartAnimation();int offset() const;void setOffset(int offset);private:inline double widthMargin() const;inline double heightMargin() const;QScopedPointer<SlipButtonPrivate> d;
};#endif // SLIPBUTTON_H
2、实现代码
#include "slipbutton.h"#include <QPropertyAnimation>
#include <QtWidgets>struct SlipButtonPrivate{int offset = 0;QColor uncheckBackgroundColor = QColor("#FFE0E0E0");QColor checkedBackgroundColor = QColor("#4da1ff");bool hover = false;QPropertyAnimation *animation;
};SlipButton::SlipButton(QWidget *parent): QAbstractButton(parent), d(new SlipButtonPrivate)
{d->animation = new QPropertyAnimation(this, "offset", this);setCheckable(true);setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);connect(this, &SlipButton::toggled, this, &SlipButton::onStartAnimation);
}SlipButton::~SlipButton()
{
}QSize SlipButton::sizeHint() const
{return QSize(100 * 1.8, 100);
}QSize SlipButton::minimumSizeHint() const
{return QSize(10 * 1.8, 10);
}void SlipButton::setCheckedBackgroundColor(const QColor& color)
{d->checkedBackgroundColor = color;update();
}QColor SlipButton::checkedBackgroundColor() const
{return d->checkedBackgroundColor;
}void SlipButton::setUncheckedBackgroundColor(const QColor &color)
{d->uncheckBackgroundColor = color;update();
}QColor SlipButton::uncheckedBackgroundColor() const
{return d->uncheckBackgroundColor;
}int SlipButton::offset() const
{return d->offset;
}void SlipButton::setOffset(int offset)
{d->offset = offset;update();
}double SlipButton::widthMargin() const
{return width() / 22.0;
}double SlipButton::heightMargin() const
{return height() / 22.0;
}void SlipButton::paintEvent(QPaintEvent* event)
{//qDebug() << offset();QWidget::paintEvent(event);QPainter painter(this);painter.setPen(Qt::NoPen);painter.setRenderHint(QPainter::Antialiasing);double w = width() - widthMargin() * 2;double h = height() - heightMargin() * 2;// 画背景QRectF rectSlot((width() - w) / 2, (height() - h) / 2, w, h);double slotRoundness = rectSlot.height() / 2;painter.setBrush(d->uncheckBackgroundColor);painter.drawRoundedRect(rectSlot, slotRoundness, slotRoundness);// 选中情况下,背景变蓝if(isEnabled() && isChecked()){QRectF rectSlotFill = rectSlot.adjusted(0, 0, offset() + h - (width() - widthMargin()), 0);painter.setBrush(d->checkedBackgroundColor);painter.drawRoundedRect(rectSlotFill, slotRoundness, slotRoundness);}QRectF rectThumb = QRectF(offset(), (height() - h) / 2, h, h);QColor colorThumbBorder = (d->hover) ? d->checkedBackgroundColor: QColor("#FFA8A8A8");painter.setBrush(colorThumbBorder);painter.drawEllipse(rectThumb);// 按钮圆点QColor colorThumb = isEnabled() ? QColor(Qt::white) : QColor("#FFE0E0E0");painter.setBrush(colorThumb);rectThumb.adjust(1.1, 1.1, -1.1, -1.1);painter.drawEllipse(rectThumb);
}void SlipButton::enterEvent(QEvent *event)
{QAbstractButton::enterEvent(event);setCursor(Qt::PointingHandCursor);d->hover = true;
}void SlipButton::leaveEvent(QEvent* event)
{QAbstractButton::leaveEvent(event);d->hover = false;
}void SlipButton::resizeEvent(QResizeEvent *event)
{QAbstractButton::resizeEvent(event);if(isChecked()){double h = height() - heightMargin() * 2;setOffset(width() - widthMargin() - h);}elsesetOffset(widthMargin());
}void SlipButton::onStartAnimation()
{double h = height() - heightMargin() * 2;double start = widthMargin();double end = width() - start - h;if(!isChecked())qSwap(start, end);// 改变参数值(offset = startValue, offset += interval_1...offset += interval_N)// 改变offset的同时,不断repaint(update)// 直到为目标值(offset = endValue)paint完成;d->animation->setStartValue(start);d->animation->setEndValue(end);d->animation->setDuration(120);d->animation->start();
}

        这个自定义控件SlipButton提供了基本的开关功能,通过鼠标点击可以在开启和关闭状态之间切换。你可以根据需要对控件进行自定义和扩展。

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "slipbutton.h"#include <QtWidgets>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{SlipButton *slipButton = new SlipButton(this);//slipButton->setFixedSize(50 * 1.8, 50);QWidget *widget = new QWidget(this);QVBoxLayout *layout = new QVBoxLayout(widget);layout->addWidget(slipButton);setCentralWidget(widget);resize(240, 140);
}MainWindow::~MainWindow()
{
}

        总结一下,笔者分享纯代码实现滑动开关控件的一种设计方法和流程,在此操作的基础上我们可以发挥想象开发出更多更有意思的控件,源码我放在此处以下地址。如有错误也请各位看官手下留情,欢迎评论区批评指正。

        谢谢你的关注和阅读,希望我的回答能帮到你。如果还有其他问题,欢迎随时向我提问。祝你一切顺利!

六、源代码下载

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

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

相关文章

dhtmlx-gantt甘特图数据展示

官网文档&#xff1a;甘特图文档 实现效果&#xff1a; 首先需要下载 dhtmlx-gantt组件 npm i dhtmlx-gantt //我项目中使用的是"dhtmlx-gantt": "^8.0.6" 这个版本&#xff0c;不同的版本api或是文档中存在的方法稍有差异 界面引用 <template>&l…

目标检测算法与应用算法 DS集成 接口相关_v0.1

目录 文章目录 目录0. 目标GPS信息、速度、加速度、航向角信息的输出1. 目标检测算法接口1.1 模型相关1.2 检测结果相关 2. 应用算法接口2.1 bool cross_line; //跨线&#xff08;变道压线检测&#xff09;2.2 bool break_in; //闯入&#xff08;目标闯入&#xff09;2.3 bool …

Linux HOOK机制与Netfilter HOOK

一. 什么是HOOK&#xff08;钩子&#xff09; 在计算机中&#xff0c;基本所有的软件程序都可以通过hook方式进行行为拦截&#xff0c;hook方式就是改变原始的执行流。 二. Linux常见的HOOK方式 1、修改函数指针。 2、用户态动态库拦截。 ①利用环境变量LD_PRELOAD和预装载机…

【Python】python中list的迭代

什么是迭代&#xff1a; 迭代其实就是遍历整个数据结构 nums [3,4,5] for n in nums:print(n)上述代码中&#xff0c;我们定义了一个nums列表&#xff0c;并且使用for循环对其进行遍历。其实整个过程就是迭代&#xff0c;所谓迭代&#xff0c;就是对数据集中每一个元素对其进…

STM32自己从零开始实操:PCB全过程

一、PCB总体分布 以下只能让大家看到各个模块大致分布在板子的哪一块&#xff0c;只能说每个人画都有自己的理由&#xff1a; 电源&#xff1a;从外部接入电源&#xff0c;5V接到中间&#xff0c;向上变成4V供给无线&#xff0c;向下变成3V供给下面的接口&#xff08;也刻意放…

无极与有极电容的区别

无极性电容与有极性电容&#xff1a;差异与应用探索 在电子元件的广阔世界里&#xff0c;电容器无疑是不可或缺的一部分。它们以储存电荷和调节电路中的电压与电流而闻名。然而&#xff0c;电容器并非一概而论&#xff0c;其中最为显著的区别之一就是无极性电容与有极性电容。…

Springboot中常见的注解及其底层实现?

Spring Boot 是一个用于简化 Spring 应用初始搭建以及开发过程的框架&#xff0c;它大量使用了注解来简化配置和提高开发效率。以下是一些常见的 Spring Boot 注解及其底层实现&#xff1a; ### 1. SpringBootApplication 这是一个复合注解&#xff0c;包含了 Configuration、…

DP讨论——访问者模式

学而时习之&#xff0c;温故而知新。 访问者模式 角色 3个角色&#xff0c;访问者类&#xff0c;被访问者类&#xff0c;管理被访问者类的类。 特色 所谓访问者模式&#xff0c;我感觉就是被访问的类的方法形参是别的对象引用&#xff0c;然后临时过来进入一下&#xff0c…

每日一练 - BGP 路由表中的团体属性

01 真题题目 下面一台路由器的输出信息&#xff0c;关于这段信息描述正确的是? A.目的网段 1.1.1.0/24 所携带的团体属性值是 NO-EXPORT&#xff0c; 表明该路由条目不能通告给任何 BGP 邻居 B.目的网段 1.1.1.0/24 所携带的图体属性值是 NO-EXPORT&#xff0c; 表明试路由…

Python面试整理-Python中的变量和赋值:理解变量的命名规则、赋值方式以及变量类型

在Python中,变量用于存储数据。以下是关于变量的命名规则、赋值方式和变量类型的详细说明: 变量的命名规则 1. 字母、数字和下划线: ● 变量名必须以字母(a-z,A-Z)或下划线(_)开头,后续字符可以是字母、数字(0-9)或下划线。 ● 例如:my_var, _var2, var3 2.

Three.JS 使用RGBELoader和CubeTextureLoader 添加环境贴图

导入RGBELoader模块&#xff1a; import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js"; 使用 addRGBEMappingk(environment, background,url) {rgbeLoader new RGBELoader();rgbeLoader.loadAsync(url).then((texture) > {//贴图模式 经纬…

三个国产数据库调研(达梦,PolarDB,TDSQL

三个国产数据库调研&#xff1a;达梦&#xff0c;PolarDB&#xff0c;TDSQL 1. 整体描述2. 达梦数据库2.1 相关网站2.2 接入工作2.3 工具使用2.4 总结 3. PolarDB数据库3.1 相关网站3.2 产品对比3.3 接入工作 4. TDSQL数据库4.1 相关网站4.2 产品对比4.3 接入工作 5. 对比总结5…

git使用-命令行+VS Code结合使用

一、Git常用命令 // 显示当分支的状态。它会列出已修改、已暂存和未跟踪的文件 git status// 列出本地仓库中所有的分支&#xff0c;其中会特殊显示当前所在分支 git branch// 在当前分支的基础上创建一个新的分支&#xff0c;并切换到这个新的分支上 git checkout -b 新分支…

问题:向上对齐对象的快捷键是: #学习方法#笔记

问题&#xff1a;向上对齐对象的快捷键是: A、T B、L C、R D、W 参考答案如图所示

做一只勤劳的小蜜蜂

机缘 成为创作者的初心&#xff0c;对我而言&#xff0c;是一个融合了个人兴趣、职业成长以及对知识传播热爱的复杂而纯粹的情感交织。回顾这段旅程的起点&#xff0c;几个核心驱动力始终引领着我前行&#xff1a; 1、记录与反思&#xff1a;在职业生涯的早期&#xff0c;我遇…

WordPress与 wp-cron.php

WordPress 傲居全球最流行的内容管理系统&#xff08;CMS&#xff09;之位&#xff0c;占据了互联网约43%的网站后台&#xff0c;这主要得益于其直观易用的用户界面以及丰富的扩展功能&#xff0c;特别是为新手用户提供了极大的便利。 然而&#xff0c;在畅享WordPress带来的便…

Leetcode 1302.层数最深子叶结点的和

大家好&#xff0c;今天我给大家分享一下我关于这个题的想法&#xff0c;我这个题过程比较复杂&#xff0c;但大家如果觉得好的话&#xff0c;就请给个免费的赞吧&#xff0c;谢谢了^ _ ^ 1.题目要求: 给你一棵二叉树的根节点 root &#xff0c;请你返回 层数最深的叶子节点的…

Go语言并发编程-Context上下文

Context上下文 Context概述 Go 1.7 标准库引入 context&#xff0c;译作“上下文”&#xff0c;准确说它是 goroutine 的上下文&#xff0c;包含 goroutine 的运行状态、环境、现场等信息。 context 主要用来在 goroutine 之间传递上下文信息&#xff0c;包括&#xff1a;取…

准备跳槽了(仍然底层为主,ue独立游戏为辅)

思考再三&#xff0c;准备跳槽了。 一、跳槽原因&#xff1a; 今年经济形势非常不好。那我为什么还要跳槽呢&#xff1f;因为干不下去了。公司是末位淘汰制&#xff0c;而我绩效垫底了。给我的整改措施中&#xff0c;部门经理让我三个月搞定60个bug&#xff0c;我觉得简直是送…

python爬虫实现简单的代理ip池

python爬虫实现简单的代理ip池 我们在普通的爬虫过程中经常遇到一些网站对ip进行封锁的 下面演示一下普通的爬虫程序 使用requests.get爬取数据 这段代码是爬取豆瓣排行榜的数据&#xff0c;使用f12来查看请求的url和数据格式 代码 def requestData():# 爬取数据的urlur…