圆环加载效果

news2024/9/21 14:26:14

效果预览

代码实现

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

class CircleProgressBar(QWidget):
    Color = QColor(37, 162, 208)  # 圆圈颜色
    Clockwise = True  # 顺时针还是逆时针
    Delta = 36

    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)

    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.Delta
        self.angle %= 360

    @pyqtProperty(QColor)
    def color(self) -> QColor:
        return self.Color

    @color.setter
    def color(self, color: QColor):
        if self.Color != color:
            self.Color = color
            self.update()

    @pyqtProperty(bool)
    def clockwise(self) -> bool:
        return self.Clockwise

    @clockwise.setter
    def clockwise(self, clockwise: bool):
        if self.Clockwise != clockwise:
            self.Clockwise = clockwise
            self.update()

    @pyqtProperty(int)
    def delta(self) -> int:
        return self.Delta

    @delta.setter
    def delta(self, delta: int):
        if self.delta != delta:
            self.delta = delta
            self.update()

    def sizeHint(self) -> QSize:
        return QSize(100, 100)

class LoadingThread(QThread):
    """模拟加载过程的线程"""
    finished = pyqtSignal()

    def run(self):
        # 在这里模拟加载过程,可以替换为实际的加载逻辑
        import time
        time.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_window
        layout = QVBoxLayout(self)

        # Set the background color for this widget
        self.setStyleSheet(f"background-color: {bg_color};")

        # Button to trigger loading animation in the main UI
        self.centerLoadButton = QPushButton("主UI中居中加载")
        self.centerLoadButton.clicked.connect(self.startLoadingInMain)
        layout.addWidget(self.centerLoadButton)

        # Button to trigger loading animation in this widget
        self.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 sys

    app = 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.Delta
    self.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 time
        time.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 sys
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

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

总结

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

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

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

相关文章

Rust使用Actix-web和SeaORM库开发WebAPI通过Swagger UI查看接口文档

本文将介绍Rust语言使用Actix-web和SeaORM库,数据库使用PostgreSQL,开发增删改查项目,同时可以通过Swagger UI查看接口文档和查看标准Rust文档 开始项目 首先创建新项目,名称为rusty_crab_api cargo new rusty_crab_apiCargo.t…

Nuxt Kit 中的页面和路由管理

title: Nuxt Kit 中的页面和路由管理 date: 2024/9/17 updated: 2024/9/17 author: cmdragon excerpt: 摘要:本文介绍了Nuxt Kit中页面和路由管理的高级功能,包括extendPages自定义页面路由、extendRouteRules定义复杂路由逻辑及addRouteMiddleware注册路由中间件。通过这…

Html css样式总结

1.Html css样式总结 1.1. 定位position 布局是html中非常重要的一部分,而定位在页面布局中也是使用频率很高的方法,本章节为定位在布局中的使用技巧和注意事项。   position定位有4个属性,分别是static(默认),absol…

第四天旅游线路预览——从换乘中心到白哈巴村

第四天:从贾登峪到喀纳斯风景区入口,晚上住宿贾登峪; 换乘中心有4 路车,喀纳斯③号车,去白哈巴村,路程时长约40分钟; 将上面的的行程安排进行动态展示,具体步骤见”Google earth st…

用Spring Boot搭建的读书笔记分享平台

第1章 绪论 1.1课题背景 计算机的普及和互联网时代的到来使信息的发布和传播更加方便快捷。用户可以通过计算机上的浏览器访问多个应用系统,从中获取一些可以满足用户需求的管理系统。网站系统有时更像是一个大型“展示平台”,用户可以选择所需的信息进入…

【Spring Security系列】如何用Spring Security集成手机验证码登录?五分钟搞定!

作者:后端小肥肠 🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案 🍊 有疑问可私信或评论区联系我。 🥑 创作不易未经允许严禁转载。 姊妹篇: 【Spring Security系列…

拖拽排序的实现示例demo

拖拽排序的实现示例demo 文章说明核心代码示例效果展示 文章说明 文章主要为了学习拖拽排序的实现思路,并且采用此示例效果来进一步理解Flip动画的使用 参考渡一前端袁老师的讲解视频 核心代码 页面源码,拖拽排序的实现代码并不复杂,但是可以…

我的标志:奇特的头像

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>与妖为邻</title><style>figure.log…

C++11(4)

万众瞩目的C11特辑来了&#xff0c;本章将继续讲解C11更新的内容&#xff0c;不过C11的内容也快接近尾声了。 目录 10。lambda表达式 11。lambda捕捉列表[] 捕捉列表说明 lambda捕捉列表实际应用 10。lambda表达式 #include<iostream> using namespace std; #inclu…

手把手教你:在微信小程序中加载map并实现拖拽添加标记定位

本文将为大家详细介绍如何在微信小程序中加载map组件&#xff0c;并实现拖拽标记定位功能。 实现步骤 1、首先&#xff0c;我们需要在项目的app.json文件中添加map组件的相关配置。如下所示&#xff1a; {"pages": ["pages/index/index"],"permiss…

robomimic基础教程(三)——自带算法

robomimic自带几个高质量的离线学习算法的实现&#xff0c;包括模仿学习和强化学习&#xff0c;并提供相关工具来辅助你轻松构建自己的学习算法。 一、模仿学习&#xff08;Imitation Learning&#xff09; 1. BC (Behavioral Cloning) Vanilla Behavioral Cloning, 旨在通过…

使用knn算法对iris数据集进行分类

程序功能 使用 scikit-learn 库中的鸢尾花数据集&#xff08;Iris dataset&#xff09;&#xff0c;并基于 KNN&#xff08;K-Nearest Neighbors&#xff0c;K近邻&#xff09;算法进行分类&#xff0c;最后评估模型的准确率。 代码 from sklearn import datasets# 加载鸢尾…

链表在开空间时候出现的问题

题目&#xff1a; 第一种写法完整答案&#xff1a; 第二种写法完整答案&#xff1a;

【机器学习】--- 自监督学习

1. 引言 机器学习近年来的发展迅猛&#xff0c;许多领域都在不断产生新的突破。在监督学习和无监督学习之外&#xff0c;自监督学习&#xff08;Self-Supervised Learning, SSL&#xff09;作为一种新兴的学习范式&#xff0c;逐渐成为机器学习研究的热门话题之一。自监督学习…

【C++题解】1996. 每个小组的最大年龄

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1996. 每个小组的最大年龄 类型&#xff1a;二维数组 题目描述&#xff1a; 同学们在操场上排成了一个 n 行 m 列的队形&#xff0c;每行的同学属于一个小组&#xff0c;请问每个小…

PCIe进阶之TL:Completion Rules TLP Prefix Rules

1 Completion Rules & TLP Prefix Rules 1.1 Completion Rules 所有的 Read、Non-Posted Write 和 AtomicOp Request 都需要返回一个 Completion。Completion 有两种类型:一种带数据负载的,一种不带数据负载的。以下各节定义了 Completion header 中每个字段的规则。 C…

【磨皮美白】基于Matlab的人像磨皮美白处理算法,Matlab处理

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于Matlab的图像磨皮美白处理&#xff0c;用matlab实现。 一、案例背景和算法介绍 …

【图像匹配】基于SURF算法的图像匹配,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于SURF算法的图像匹配&#xff0c;用matlab实现。 一、案例背景和算法介绍 前…

7天速成前端 ------学习日志 (继苍穹外卖之后)

前端速成计划总结&#xff1a; 全26h课程&#xff0c;包含html&#xff0c;css&#xff0c;js&#xff0c;vue3&#xff0c;预计7天内学完。 起始日期&#xff1a;9.16 预计截止&#xff1a;9.22 每日更新&#xff0c;学完为止。 学前计划 课…

文字loading加载

效果 1. 导入库 import sys from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QPainter, QFont, QColor, QBrush from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QProgressBar, QLabel 代码首先导入了P…