效果
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) # 每个字符的初始透明度为0
self.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 = True
for i in range(len(self.baseText)):
if self.dropDelays[i] > 0:
self.dropDelays[i] -= 1
else:
if self.alphaValues[i] < 255:
self.alphaValues[i] = min(255, self.alphaValues[i] + 15)
self.yValues[i] += 2
complete = False
self.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 += 5
self.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...”文字的逐字动画效果,每个字母依次从上方淡入并落下。
- 一个模拟耗时操作的后台任务。
- 在任务完成后,进度条逐渐填满。