当前位置: 首页 > news >正文

圆环加载效果

效果预览

代码实现

from PyQt5.QtCore import QSize, pyqtProperty, QTimer, Qt, QThread, pyqtSignal
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QLabel, QGridLayoutclass CircleProgressBar(QWidget):Color = QColor(37, 162, 208)  # 圆圈颜色Clockwise = True  # 顺时针还是逆时针Delta = 36def __init__(self, *args, color=None, clockwise=True, **kwargs):super(CircleProgressBar, self).__init__(*args, **kwargs)self.angle = 0self.Clockwise = clockwiseif color:self.Color = colorself._timer = QTimer(self, timeout=self.update)def start(self):"""启动进度条的加载动画"""self._timer.start(100)  # 开始定时器def stop(self):"""停止进度条的加载动画并删除控件"""self._timer.stop()self.deleteLater()  # 删除控件并释放资源def paintEvent(self, event):super(CircleProgressBar, self).paintEvent(event)painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)painter.translate(self.width() / 2, self.height() / 2)side = min(self.width(), self.height())painter.scale(side / 100.0, side / 100.0)painter.rotate(self.angle)painter.save()painter.setPen(Qt.NoPen)color = self.Color.toRgb()for i in range(11):color.setAlphaF(1.0 * i / 10)painter.setBrush(color)painter.drawEllipse(30, -10, 20, 20)painter.rotate(36)painter.restore()self.angle += self.Delta if self.Clockwise else -self.Deltaself.angle %= 360@pyqtProperty(QColor)def color(self) -> QColor:return self.Color@color.setterdef color(self, color: QColor):if self.Color != color:self.Color = colorself.update()@pyqtProperty(bool)def clockwise(self) -> bool:return self.Clockwise@clockwise.setterdef clockwise(self, clockwise: bool):if self.Clockwise != clockwise:self.Clockwise = clockwiseself.update()@pyqtProperty(int)def delta(self) -> int:return self.Delta@delta.setterdef delta(self, delta: int):if self.delta != delta:self.delta = deltaself.update()def sizeHint(self) -> QSize:return QSize(100, 100)class LoadingThread(QThread):"""模拟加载过程的线程"""finished = pyqtSignal()def run(self):# 在这里模拟加载过程,可以替换为实际的加载逻辑import timetime.sleep(5)  # 模拟加载时间self.finished.emit()  # 加载完成后发出信号class CustomWidget(QWidget):"""每个子控件,包含两个按钮"""def __init__(self, main_window, bg_color, *args, **kwargs):super(CustomWidget, self).__init__(*args, **kwargs)self.main_window = main_windowlayout = QVBoxLayout(self)# Set the background color for this widgetself.setStyleSheet(f"background-color: {bg_color};")# Button to trigger loading animation in the main UIself.centerLoadButton = QPushButton("主UI中居中加载")self.centerLoadButton.clicked.connect(self.startLoadingInMain)layout.addWidget(self.centerLoadButton)# Button to trigger loading animation in this widgetself.localLoadButton = QPushButton("本控件中加载")self.localLoadButton.clicked.connect(self.startLoadingInLocal)layout.addWidget(self.localLoadButton)def startLoadingInMain(self):"""在主窗口的中心显示加载动画"""self.main_window.startLoadingInCenter()def startLoadingInLocal(self):"""在本控件内部显示加载动画"""self.main_window.startLoadingInWidget(self)class Window(QWidget):def __init__(self, *args, **kwargs):super(Window, self).__init__(*args, **kwargs)self.initUI()def initUI(self):layout = QGridLayout(self)self.setLayout(layout)# 创建四个子控件,并为每个控件指定不同的背景颜色widget1 = CustomWidget(self, "lightblue")widget2 = CustomWidget(self, "lightgreen")widget3 = CustomWidget(self, "lightcoral")widget4 = CustomWidget(self, "lightyellow")layout.addWidget(widget1, 0, 0)layout.addWidget(widget2, 0, 1)layout.addWidget(widget3, 1, 0)layout.addWidget(widget4, 1, 1)def startLoadingInCenter(self):"""在主窗口中心显示加载动画"""self.progressBar = CircleProgressBar(self)  # 动态创建进度条self.progressBar.setFixedSize(100, 100)self.progressBar.show()# 设置进度条在主窗口中心self.progressBar.move(self.width() // 2 - self.progressBar.width() // 2,self.height() // 2 - self.progressBar.height() // 2)self.progressBar.start()  # 手动启动进度条动画# 启动加载线程self.loadingThread = LoadingThread()self.loadingThread.finished.connect(self.progressBar.stop)self.loadingThread.start()def startLoadingInWidget(self, widget):"""在指定的小部件内显示加载动画"""self.progressBar = CircleProgressBar(widget)  # 在小部件中创建进度条self.progressBar.setFixedSize(50, 50)self.progressBar.show()# 设置进度条在小部件中心self.progressBar.move(widget.width() // 2 - self.progressBar.width() // 2,widget.height() // 2 - self.progressBar.height() // 2)self.progressBar.start()  # 手动启动进度条动画# 启动加载线程self.loadingThread = LoadingThread()self.loadingThread.finished.connect(self.progressBar.stop)self.loadingThread.start()if __name__ == '__main__':import sysapp = QApplication(sys.argv)w = Window()w.show()sys.exit(app.exec_())

具体介绍

1. 导入必要模块

 
from PyQt5.QtCore import QSize, pyqtProperty, QTimer, Qt, QThread, pyqtSignal
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QLabel, QGridLayout

  • QSize: 控件的尺寸类。
  • pyqtProperty: 用于创建自定义的属性,使其可以与PyQt的信号和槽系统协作。
  • QTimer: 用于控制加载动画的定时器。
  • Qt: 包含常用的Qt标志和属性(例如布局方向、对齐方式等)。
  • QThreadpyqtSignal: 用于多线程处理,QThread允许后台执行任务,pyqtSignal用于在任务完成时发出信号。
  • QColorQPainter: 用于绘制和处理颜色的类。
  • QWidget 及其子类用于创建UI控件(例如按钮、布局、标签等)。

2. CircleProgressBar 类

 
class CircleProgressBar(QWidget):Color = QColor(37, 162, 208)  # 圆圈颜色Clockwise = True  # 是否顺时针旋转Delta = 36  # 每次旋转的角度增量

  • 该类定义了一个自定义的环形进度条,并继承自 QWidget
  • 主要负责绘制并控制环形加载动画。
初始化方法
 
def __init__(self, *args, color=None, clockwise=True, **kwargs):super(CircleProgressBar, self).__init__(*args, **kwargs)self.angle = 0  # 当前旋转的角度self.Clockwise = clockwise  # 控制旋转方向if color:self.Color = color  # 可以通过参数自定义进度条颜色self._timer = QTimer(self, timeout=self.update)  # 定时器用于定时更新动画

  • angle:控制动画的当前角度。
  • QTimer:每隔100ms触发一次,调用update()方法刷新绘制。
启动和停止动画的方法
def start(self):"""启动进度条的加载动画"""self._timer.start(100)def stop(self):"""停止进度条的加载动画并删除控件"""self._timer.stop()self.deleteLater()  # 删除控件以释放资源

  • start():启动定时器,进而启动动画。
  • stop():停止动画并销毁该进度条控件。
绘制环形动画
 
def paintEvent(self, event):super(CircleProgressBar, self).paintEvent(event)painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)painter.translate(self.width() / 2, self.height() / 2)side = min(self.width(), self.height())painter.scale(side / 100.0, side / 100.0)painter.rotate(self.angle)painter.save()painter.setPen(Qt.NoPen)color = self.Color.toRgb()for i in range(11):color.setAlphaF(1.0 * i / 10)painter.setBrush(color)painter.drawEllipse(30, -10, 20, 20)painter.rotate(36)painter.restore()self.angle += self.Delta if self.Clockwise else -self.Deltaself.angle %= 360

  • paintEvent():负责绘制进度条的环形动画。
    • painter.translate():将画布的坐标系中心移动到控件的中心位置。
    • painter.scale():缩放画布,以适应控件的大小。
    • painter.rotate():旋转环形的每个小圆点。
    • color.setAlphaF():为每个圆点设置透明度,透明度从最低到最高,形成渐隐效果。
    • painter.drawEllipse():绘制每个小圆点。
    • 每次更新动画时,角度都会增加或减少,形成旋转效果。
自定义属性
  • 使用 pyqtProperty 定义了自定义的属性 color, clockwise, delta,使它们能够与PyQt的属性系统兼容。

3. LoadingThread 类

 
class LoadingThread(QThread):"""模拟加载过程的线程"""finished = pyqtSignal()def run(self):import timetime.sleep(5)  # 模拟加载时间self.finished.emit()  # 加载完成后发出信号

  • 该类继承自 QThread,用于模拟后台任务(这里通过 time.sleep(5) 模拟了5秒的加载过程)。
  • finished 信号用于通知主线程加载完成。
  • 主要用于模拟耗时任务,同时保持UI的响应性。

4. CustomWidget 类

 
class CustomWidget(QWidget):"""每个子控件,包含两个按钮"""def __init__(self, main_window, bg_color, *args, **kwargs):super(CustomWidget, self).__init__(*args, **kwargs)layout = QVBoxLayout(self)self.setStyleSheet(f"background-color: {bg_color};")self.centerLoadButton = QPushButton("主UI中居中加载")self.centerLoadButton.clicked.connect(self.startLoadingInMain)layout.addWidget(self.centerLoadButton)self.localLoadButton = QPushButton("本控件中加载")self.localLoadButton.clicked.connect(self.startLoadingInLocal)layout.addWidget(self.localLoadButton)

  • 这是自定义的控件,每个控件内部包含两个按钮:
    • centerLoadButton:触发主窗口的居中加载动画。
    • localLoadButton:在该控件内显示加载动画。
  • 每个控件的背景颜色由参数 bg_color 决定。

5. Window 类

 
class Window(QWidget):def __init__(self, *args, **kwargs):super(Window, self).__init__(*args, **kwargs)self.initUI()def initUI(self):layout = QGridLayout(self)self.setLayout(layout)# 创建四个子控件,并为每个控件指定不同的背景颜色widget1 = CustomWidget(self, "lightblue")widget2 = CustomWidget(self, "lightgreen")widget3 = CustomWidget(self, "lightcoral")widget4 = CustomWidget(self, "lightyellow")layout.addWidget(widget1, 0, 0)layout.addWidget(widget2, 0, 1)layout.addWidget(widget3, 1, 0)layout.addWidget(widget4, 1, 1)

  • Window 类是应用的主窗口,继承自 QWidget
  • 它使用了 QGridLayout 布局,将四个不同颜色的 CustomWidget 放置在窗口的不同位置。
在窗口中央显示加载动画
 
def startLoadingInCenter(self):"""在主窗口中心显示加载动画"""self.progressBar = CircleProgressBar(self)self.progressBar.setFixedSize(100, 100)self.progressBar.show()self.progressBar.move(self.width() // 2 - self.progressBar.width() // 2,self.height() // 2 - self.progressBar.height() // 2)self.progressBar.start()self.loadingThread = LoadingThread()self.loadingThread.finished.connect(self.progressBar.stop)self.loadingThread.start()

  • 该方法在主窗口中心显示环形进度条。
  • 创建进度条后,启动加载动画,并启动 LoadingThread 模拟加载任务。
  • 加载完成后,停止并删除进度条。
在子控件内显示加载动画
 
def startLoadingInWidget(self, widget):"""在指定的小部件内显示加载动画"""self.progressBar = CircleProgressBar(widget)self.progressBar.setFixedSize(50, 50)self.progressBar.show()self.progressBar.move(widget.width() // 2 - self.progressBar.width() // 2,widget.height() // 2 - self.progressBar.height() // 2)self.progressBar.start()self.loadingThread = LoadingThread()self.loadingThread.finished.connect(self.progressBar.stop)self.loadingThread.start()

  • 该方法在特定的子控件内显示环形进度条动画。

6. 主程序执行

 
if __name__ == '__main__':import sysapp = QApplication(sys.argv)w = Window()w.show()sys.exit(app.exec_())

  • 程序的入口,创建 QApplication 实例并启动事件循环。

总结

  • 该程序展示了如何创建一个带有环形加载动画的PyQt5应用程序。
  • CircleProgressBar 负责绘制并控制动画,LoadingThread 模拟后台任务。
  • 主窗口 Window 包含四个不同颜色的子控件,用户可以选择在主窗口或子控件内显示加载动画。

相关文章:

圆环加载效果

效果预览 代码实现 from PyQt5.QtCore import QSize, pyqtProperty, QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QColor, QPainter from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QLabel, QGridLayoutclass Cir…...

leetcode - 分治思想

分治 - 快排 这里快排我们统一使用 数组分三块 和 随机产生基准值的方法实现排序 数组分三块: . - 力扣(LeetCode) 整个思想即将数组按照基准值分为三个区间 , 具体实现: 三指针实现. 遍历指针 , 左区间右边界指针 , 右区间左边界指针 class Solutio…...

Java面试题·解释题·单例模式、工厂模式、代理模式部分

系列文章目录 Java面试题解释题JavaSE部分 Java面试题解释题框架部分 Java面试题解释题单例模式、工厂模式、代理模式部分 文章目录 系列文章目录前言一、设计模式1. 单例模式1.1 单例模式的定义1.2 单例模式的实现方法 2. 工厂模式2.1 工厂模式的定义2.2 工厂模式的实现方法2…...

如何编写智能合约——基于长安链的Go语言的合约开发

场景设计:文件存证系统 在数字化时代,文件存证和版本追踪变得越来越重要。设想一个场景:在一个法律事务管理系统中,用户需要提交和管理各种文件的版本记录,以确保每个文件在不同时间点的状态可以被准确追踪。文件可能经…...

【PHP代码审计】PHP基础知识

🌝博客主页:菜鸟小羊 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 php简介 php是什么? php(全称:Hypertext Preprocessor,即超文本预处理器&…...

大模型笔记03--快速体验dify

大模型笔记03--快速体验dify 介绍部署&测试部署 dify测试dify对接本地ollama大模型对接阿里云千问大模型在个人网站中嵌入dify智能客服 注意事项说明 介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务(Backend as Service)…...

Linux常用命令以及操作技巧

🌏个人博客主页:意疏-CSDN博客 希望文章能够给到初学的你一些启发~ 如果觉得文章对你有帮助的话,点赞 关注 收藏支持一下笔者吧~ 阅读指南: 开篇说明帮助命令常见的七个linux操作终端实用的技巧跟文件目录…...

C语言 | Leetcode C语言题解之题409题最长回文串

题目&#xff1a; 题解&#xff1a; int longestPalindrome(char * s) {int c[128]{0},ret0;for(int i0;i<strlen(s);i){c[s[i]];}for(int i0;i<128;i){retc[i]-c[i]%2;}return ret(ret!strlen(s)); }...

FreeSql 全面指南:从基础到高级实战,深入解析读写分离与导航属性

FreeSql 使用详解&#xff1a;从入门到高级 FreeSql 是一个开源的、轻量级的 ORM 框架&#xff0c;它为 .NET 开发人员提供了丰富的功能&#xff0c;包括 CRUD 操作、读写分离、多租户、导航属性支持等。相比于 Entity Framework Core&#xff0c;FreeSql 在性能和特性上有一些…...

深度学习之微积分预备知识点

极限&#xff08;Limit&#xff09; 定义&#xff1a;表示某一点处函数趋近于某一特定值的过程&#xff0c;一般记为 极限是一种变化状态的描述&#xff0c;核心思想是无限靠近而永远不能到达 公式&#xff1a; 表示 x 趋向 a 时 f(x) 的极限。 知识点口诀解释极限的存在左…...

动态内存

动态内存分配函数&#xff1a;在程序运行时为变量或数据结构开辟的内存空间的函数。 有三个重要的动态分配函数&#xff1a;malloc、calloc、realloc。 动态内存分配函数 malloc 这个函数是向内存中申请一块连续的空间&#xff0c;返回一个指向这个块空间的指针。 如果开辟成…...

C/C++实现植物大战僵尸(PVZ)(打地鼠版)

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 游戏…...

C++ 科目二 智能指针 [weak_ptr] (解决shared_ptr的循环引用问题)

shared_ptr引入的重复计数问题&#xff0c;导致内存泄漏 using namespace std; class CFather; class CSon;class CFather { public:CFather(){}void Set(shared_ptr<CSon> pson){Pson pson;}shared_ptr<CSon> Pson; };class CSon { public:CSon(){}void Set(sha…...

解决RabbitMQ设置TTL过期后不进入死信队列

解决RabbitMQ设置TTL过期后不进入死信队列 问题发现问题解决方法一&#xff1a;只监听死信队列&#xff0c;在死信队列里面处理业务逻辑方法二&#xff1a;改为自动确认模式 问题发现 最近再学习RabbitMQ过程中&#xff0c;看到关于死信队列内容&#xff1a; 来自队列的消息可…...

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】005 - Kernel 入口 C 函数 start_kernel() 源码分析

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】005 - Kernel 入口 C 函数 start_kernel 源码分析 系列文章汇总:《鸿蒙OH-v5.0源码分析之 Uboot+Kernel 部分】000 - 文章链接汇总》 本文链接:《【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】005 - Kernel 入口 C 函数 start_ke…...

EndnoteX9安装及使用教程

EndnoteX9安装及使用教程 一、EndNote安装 1.1 下载 这里提供一个下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1RlGJksQ67YDIhz4tBmph6Q 提取码&#xff1a;5210 解压完成后&#xff0c;如下所示&#xff1a; 1.2 安装 双击右键进行安装 安装比较简单…...

SQL:子查询

子查询是SQL中强大的功能之一&#xff0c;它允许在一个查询内部嵌套另一个查询&#xff0c;以便处理更复杂的逻辑或数据检索需求。子查询可以用在SELECT、FROM、WHERE、HAVING、IN、ANY、ALL等子句中&#xff0c;根据使用场景和目的的不同&#xff0c;子查询可以分为多种类型。…...

C语言刷题日记(附详解)(5)

一、选填部分 第一题: 下面代码在64位系统下的输出为( ) void print_array(int arr[]) {int n sizeof(arr) / sizeof(arr[0]);for (int i 0; i < n; i)printf("%d", arr[i]); } int main() {int arr[] { 1,2,3,4,5 };print_array(arr);return 0; } A . 1…...

开源加密软件简介

开源加密软件是指源代码公开、可供任何人查看、修改和分发的加密软件。这类软件通常由社区维护&#xff0c;具有高度的透明性和安全性。 1. GnuPG (GNU Privacy Guard) 简介&#xff1a;GnuPG是一种基于OpenPGP标准的加密和签名工具&#xff0c;广泛应用于电子邮件加密和文件…...

【C++学习】 IO 流揭秘:高效数据读写的最佳实践

✨ 今朝有酒今朝醉&#xff0c;明日愁来明日愁 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3f…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...