效果
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
代码首先导入了PyQt5库中的几个模块:
QTimer
: 用于定时执行某些操作,比如动画的逐帧更新。Qt
,QThread
,pyqtSignal
:Qt
用于定义窗口属性和对齐方式,QThread
用于后台任务,pyqtSignal
用于发出信号通知任务完成。QPainter
,QFont
,QColor
,QBrush
: 这些类用于绘制自定义的内容,如绘制文本、设置字体、颜色和背景。QApplication
,QWidget
,QVBoxLayout
,QPushButton
,QProgressBar
,QLabel
: 用于构建基础的GUI界面。
2. LoadingDialog 类
class LoadingDialog(QLabel):def __init__(self, parent=None, size_ratio=0.3):super().__init__(parent, Qt.Dialog | Qt.FramelessWindowHint)self.setAttribute(Qt.WA_TranslucentBackground)self.baseText = "Loading..."self.resize(int(parent.width() * size_ratio), int(parent.height() * size_ratio))self.setAlignment(Qt.AlignCenter)self.animation_complete = False
- 该类继承自
QLabel
,主要负责显示“Loading...”字样的动画效果。 size_ratio
决定了加载对话框相对于父窗口的大小(默认是30%的父窗口大小)。Qt.FramelessWindowHint
让窗口没有边框,Qt.WA_TranslucentBackground
让背景透明。baseText
是动画中显示的文本“Loading...”。
定时器和动画状态:
self.timer = QTimer() self.timer.timeout.connect(self.updateLoadingText)
self.resetAnimation()
- 使用定时器
QTimer
来控制动画帧的更新。每15毫秒调用一次updateLoadingText
方法,控制每个字母的状态。
resetAnimation()方法:
def resetAnimation(self):self.alphaValues = [0] * len(self.baseText) # 每个字符的初始透明度为0self.yValues = [-50] * len(self.baseText) # 所有字符从视图上方开始self.dropDelays = [i * 5 for i in range(len(self.baseText))] # 每个字符的下降有不同的延迟self.animation_complete = False
- 该方法初始化动画的状态:
alphaValues
:用于控制每个字符的透明度,实现淡入效果。yValues
:控制字符的垂直位置,从-50开始,即所有字符从视图上方掉落。dropDelays
:为每个字符设置不同的延迟,使它们不会同时出现。
startAnimation()与stopAnimation()方法:
def startAnimation(self):self.resetAnimation()self.centerInParent()self.timer.start(15)self.show()def stopAnimation(self):self.timer.stop()self.hide()
startAnimation()
重置动画状态,并启动定时器使字符逐帧下降。stopAnimation()
停止定时器并隐藏对话框。
updateLoadingText()方法:
def updateLoadingText(self):complete = Truefor i in range(len(self.baseText)):if self.dropDelays[i] > 0:self.dropDelays[i] -= 1else:if self.alphaValues[i] < 255:self.alphaValues[i] = min(255, self.alphaValues[i] + 15)self.yValues[i] += 2complete = Falseself.update()if complete and not self.animation_complete:self.resetAnimation()
- 该方法控制每个字符的淡入(通过透明度变化)和掉落(通过Y轴位置变化)。
complete
变量用于判断动画是否完成。
paintEvent()方法:
def paintEvent(self, event):painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)painter.setFont(QFont("Arial", 18))for i, char in enumerate(self.baseText):char_x = int(start_x + painter.fontMetrics().width(self.baseText[:i]))char_y = int(start_y + self.yValues[i])painter.setPen(QColor(100, 181, 246, self.alphaValues[i]))painter.drawText(char_x, char_y, char)
- 该方法绘制每个字符的位置和透明度,随着定时器的更新不断刷新界面。
3. BackgroundTask 类
class BackgroundTask(QThread):finished = pyqtSignal()def run(self):QThread.sleep(5)self.finished.emit()
BackgroundTask
类继承自QThread
,用于模拟后台任务。run()
方法通过QThread.sleep(5)
模拟5秒的延迟,任务完成后发出finished
信号通知主界面。
4. LoadingWidget 类
class LoadingWidget(QWidget):def __init__(self):super().__init__()self.initUI()self.overlay = LoadingDialog(self)self.background_task = BackgroundTask()self.background_task.finished.connect(self.onLoadComplete)
LoadingWidget
类是主窗口,包含按钮和进度条。- 它创建了
LoadingDialog
实例用于显示加载动画,并设置了一个后台任务BackgroundTask
来处理耗时操作。 - 当后台任务完成时,会调用
onLoadComplete
方法。
initUI()方法:
def initUI(self):layout = QVBoxLayout()self.button = QPushButton('开始加载', self)self.button.clicked.connect(self.startLoading)layout.addWidget(self.button)self.progressBar = QProgressBar(self)layout.addWidget(self.progressBar)self.setLayout(layout)self.setWindowTitle('逐字加载动画示例')self.resize(400, 300)self.progressTimer = QTimer()self.progressTimer.timeout.connect(self.updateProgress)self.progress = 0
initUI()
方法创建了一个按钮和进度条,并将它们添加到布局中。
startLoading()方法:
def startLoading(self):self.overlay.startAnimation()self.background_task.start()
startLoading()
启动加载动画并开始后台任务。
onLoadComplete()与updateProgress()方法:
def onLoadComplete(self):self.overlay.stopAnimation()self.progressTimer.start(100)def updateProgress(self):self.progress += 5self.progressBar.setValue(self.progress)if self.progress >= 100:self.progressTimer.stop()
- 当后台任务完成时,
onLoadComplete()
停止加载动画并启动进度条更新。 updateProgress()
每100毫秒更新一次进度条,直到进度条填满为止。
5. 主程序
if __name__ == '__main__':app = QApplication(sys.argv)ex = LoadingWidget()ex.show()sys.exit(app.exec_())
- 程序的入口,创建
QApplication
实例并显示主窗口。
总结
这个程序实现了一个具有动画加载效果的PyQt5 GUI应用。主要特点包括:
- “Loading...”文字的逐字动画效果,每个字母依次从上方淡入并落下。
- 一个模拟耗时操作的后台任务。
- 在任务完成后,进度条逐渐填满。