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

PyQt5中QProgressDialog进度条提前终止问题求助

问题分析与解决方案

问题原因

  1. QProgressDialog自动关闭特性:QProgressDialog默认autoClose属性为True,当进度值达到设定的最大值(100)时会自动关闭窗口。你的代码在开始处理最后一个文件时就发送了100%的进度信号,此时文件还在读取、合并,后续还有保存操作,进度条因此提前关闭。
  2. 进度更新时机错误:进度计算和信号发射放在了处理每个文件之前,导致最后一个文件的处理、保存阶段没有进度反馈,且直接触发进度条的自动关闭逻辑。

修复方案

1. 禁用进度条自动关闭

创建QProgressDialog时,关闭自动关闭和自动重置特性,手动通过mergeFinished信号控制关闭时机:

self.progress = QProgressDialog(self)
self.progress.setLabelText("Merging files...")
self.progress.setCancelButton(None)
self.progress.setRange(0, 100)
# 新增以下两行,禁用自动关闭与重置
self.progress.setAutoClose(False)
self.progress.setAutoReset(False)
self.progress.show()

2. 调整进度更新时机

将进度信号的发射移到每个文件处理完成之后,确保进度值对应实际完成的工作量:

def merge_excel(self, files):
    wb_combined = Workbook()
    ws_combined = wb_combined.active

    total_files = len(files)
    for index, filename in enumerate(files, 1):
        wb = load_workbook(filename, read_only=False)
        ws = wb.active
        for row in ws.iter_rows(values_only=True):
            ws_combined.append(row)
        
        # 处理完当前文件后再计算并发送进度
        progress = int((index / total_files) * 100)
        self.progressChanged.emit(progress)

    wb_combined.save("merged_file.xlsx")
    self.mergeFinished.emit()

3. 优化线程与信号传递

不需要将信号作为参数传递给ExcelMerger,直接使用ExcelMerger自身的progressChanged信号即可,简化MergeThread的实现:

class MergeThread(QThread):
    def __init__(self, files, excel_merger):
        super().__init__()
        self.files = files
        self.excel_merger = excel_merger

    def run(self):
        self.excel_merger.merge_excel(self.files)

启动线程时改为:

self.thread = MergeThread(files, self.excel_merger)
self.thread.start()

修改后的完整代码

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QFileDialog, QProgressDialog, QWidget
from PyQt5.QtCore import pyqtSignal, QObject, QThread
from openpyxl import load_workbook, Workbook


class ExcelMerger(QObject):
    progressChanged = pyqtSignal(int)
    mergeFinished = pyqtSignal()

    def merge_excel(self, files):
        wb_combined = Workbook()
        ws_combined = wb_combined.active

        total_files = len(files)
        for index, filename in enumerate(files, 1):
            wb = load_workbook(filename, read_only=False)
            ws = wb.active
            for row in ws.iter_rows(values_only=True):
                ws_combined.append(row)
            
            # 处理完文件后更新进度
            progress = int((index / total_files) * 100)
            self.progressChanged.emit(progress)

        wb_combined.save("merged_file.xlsx")
        self.mergeFinished.emit()


class MergeThread(QThread):
    def __init__(self, files, excel_merger):
        super().__init__()
        self.files = files
        self.excel_merger = excel_merger

    def run(self):
        self.excel_merger.merge_excel(self.files)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.excel_merger = ExcelMerger()
        self.excel_merger.progressChanged.connect(self.on_progress_changed)
        self.excel_merger.mergeFinished.connect(self.on_merge_finished)

    def initUI(self):
        self.setWindowTitle('Excel Merger')
        self.setGeometry(100, 100, 300, 200)

        layout = QVBoxLayout()

        self.merge_btn = QPushButton('Merge Excel Files', self)
        self.merge_btn.clicked.connect(self.merge_files)
        layout.addWidget(self.merge_btn)

        self.widget = QWidget()
        self.widget.setLayout(layout)
        self.setCentralWidget(self.widget)

    def merge_files(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        files, _ = QFileDialog.getOpenFileNames(self, "Select Excel files to merge", "", "Excel Files (*.xlsx *.xls)", options=options)

        if files:
            self.progress = QProgressDialog(self)
            self.progress.setLabelText("Merging files...")
            self.progress.setCancelButton(None)
            self.progress.setRange(0, 100)
            # 禁用自动关闭和自动重置
            self.progress.setAutoClose(False)
            self.progress.setAutoReset(False)
            self.progress.show()

            self.thread = MergeThread(files, self.excel_merger)
            self.thread.start()

    def on_progress_changed(self, value):
        self.progress.setValue(value)

    def on_merge_finished(self):
        self.progress.close()
        print("Files merged successfully.")


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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:06:05