You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为PyQt耗时线程添加圆形等待指示器?

PyQt 实现圆形等待指示器(配合耗时线程)

嗨,我来给你分享两个实用的方案,不用进度条或启动屏就能实现圆形等待指示器,完美适配你的耗时线程场景~

方案一:用 QMovie 加载 GIF 指示器(简单快捷)

这种方法最省心,找个现成的圆形加载GIF,用QMovie就能直接驱动,不用自己写动画逻辑。

步骤:

  1. 准备一个圆形加载的GIF图片(比如常见的旋转圆圈样式)
  2. 在主窗口中添加一个QLabel作为指示器容器,初始隐藏
  3. 把GIF加载到QMovie,关联到QLabel
  4. 通过线程的started()和finished()信号,控制指示器的显示/隐藏以及动画的启停

代码示例:

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QLabel
from PyQt5.QtCore import QThread, pyqtSignal, QMovie
import sys
import time

# 耗时任务线程
class WorkerThread(QThread):
    finished = pyqtSignal()

    def run(self):
        # 模拟耗时操作
        time.sleep(3)
        self.finished.emit()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("圆形等待指示器示例")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        # 启动任务按钮
        self.start_btn = QPushButton("开始耗时任务")
        self.start_btn.clicked.connect(self.start_task)
        layout.addWidget(self.start_btn)

        # 圆形等待指示器
        self.loading_label = QLabel(self)
        # 加载GIF,替换成你的GIF路径
        self.movie = QMovie("loading_circle.gif")
        self.loading_label.setMovie(self.movie)
        self.loading_label.hide()  # 初始隐藏
        layout.addWidget(self.loading_label)

        # 初始化线程
        self.worker_thread = WorkerThread()
        self.worker_thread.started.connect(self.show_loading)
        self.worker_thread.finished.connect(self.hide_loading)

    def start_task(self):
        self.start_btn.setEnabled(False)  # 防止重复点击
        self.worker_thread.start()

    def show_loading(self):
        self.loading_label.show()
        self.movie.start()

    def hide_loading(self):
        self.movie.stop()
        self.loading_label.hide()
        self.start_btn.setEnabled(True)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

方案二:自定义绘制圆形动画(纯代码,更灵活)

如果不想依赖外部GIF,可以自己绘制一个旋转的圆形指示器,完全用PyQt的绘图API实现,样式还能自定义。

步骤:

  1. 继承QWidget自定义一个圆形指示器组件
  2. 用QTimer定时更新旋转角度,重写paintEvent绘制旋转的圆弧
  3. 同样通过线程信号控制组件的显示/隐藏和动画启停

代码示例:

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QThread, pyqtSignal, QTimer, Qt
from PyQt5.QtGui import QPainter, QPen
import sys
import time

# 耗时任务线程
class WorkerThread(QThread):
    finished = pyqtSignal()

    def run(self):
        time.sleep(3)
        self.finished.emit()

# 自定义圆形等待指示器
class CircularProgress(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFixedSize(40, 40)  # 设置指示器大小
        self.angle = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_angle)

    def update_angle(self):
        self.angle = (self.angle + 10) % 360
        self.update()  # 触发重绘

    def start_animation(self):
        self.timer.start(30)  # 每30ms更新一次角度
        self.show()

    def stop_animation(self):
        self.timer.stop()
        self.hide()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.translate(self.width()/2, self.height()/2)  # 移到中心
        painter.rotate(self.angle)

        # 绘制旋转的圆弧
        pen = QPen(Qt.blue, 4)
        pen.setCapStyle(Qt.RoundCap)
        painter.setPen(pen)
        # 绘制270度的圆弧,留出缺口
        painter.drawArc(-self.width()/2 + 2, -self.height()/2 + 2, 
                        self.width()-4, self.height()-4, 0, 270*16)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("自定义圆形等待指示器")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        self.start_btn = QPushButton("开始耗时任务")
        self.start_btn.clicked.connect(self.start_task)
        layout.addWidget(self.start_btn)

        # 添加自定义指示器
        self.circular_progress = CircularProgress(self)
        self.circular_progress.hide()
        layout.addWidget(self.circular_progress, alignment=Qt.AlignCenter)

        self.worker_thread = WorkerThread()
        self.worker_thread.started.connect(self.circular_progress.start_animation)
        self.worker_thread.finished.connect(self.circular_progress.stop_animation)
        self.worker_thread.finished.connect(lambda: self.start_btn.setEnabled(True))

    def start_task(self):
        self.start_btn.setEnabled(False)
        self.worker_thread.start()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

注意事项:

  • 不管用哪种方案,都要确保耗时任务在子线程中执行,绝对不能阻塞主线程,否则指示器会卡顿甚至不显示
  • 自定义指示器的样式可以随意调整:比如修改颜色、圆弧长度、旋转速度,甚至添加渐变效果
  • 如果需要在多个地方使用指示器,可以把它封装成单独的组件,复用更方便

内容的提问来源于stack exchange,提问作者0Nicholas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:14:43