对一个类实现QProgressBar

0 投票
2 回答
1861 浏览
提问于 2025-04-18 23:31

我的PyQt程序有两个小部件(比如选择文件等),然后是一个主窗口,用来显示解析后的文件结果。

这个程序在处理小文件时运行得很好,但当尝试解析较大的文件时,它会卡住(显示“未响应”),大约过了30秒后才会显示结果。

我想在主窗口打开之前先实现一个QDialog。这个QDialog里会有一个进度条,让用户知道主窗口什么时候会打开。

这个进度条需要根据主窗口弹出前的时间来设置。

实现这个的最佳方法是什么?我见过一些例子,但那些进度条都是设置为固定的时间,而不是在处理(解析)完成时更新。

我现在有以下代码来打开主窗口。

def openWidgetMain(self):
        self.WidgetMain = WidgetMain()
        self.WidgetMain.show()
        self.close()

这个窗口的所有处理都是在它打开时完成的。那么我该如何连接QProgressBar呢?

2 个回答

1

把你需要长时间运行的过程放到一个线程里去。你可以看看这个链接了解更多信息:http://qt-project.org/doc/qt-5/threads-technologies.html。然后从这个线程里发出一个信号,来更新你的进度条。这样的话,你的应用程序就不会卡住,用户也能看到进度。

不过,显示进度条上百分比的具体数值还是得由你的加载程序来决定。如果你无法计算出准确的百分比,可以尝试做一些估算,比如根据文件的大小和已经处理的部分来判断。

0

首先,最好的实现方法是,你需要估算一下你的加载进度文件。接下来,使用 QtCore.QThread 来创建一个后台进程。最后,把你的进度回调放到 QtGui.QMainWindow 里。

这里有个简单的例子:

import sys
import time
from PyQt4 import QtGui
from PyQt4 import QtCore

class QCustomThread (QtCore.QThread):
    startLoad    = QtCore.pyqtSignal(int)
    progressLoad = QtCore.pyqtSignal(int)
    statusLoad   = QtCore.pyqtSignal(bool)

    def __init__ (self, parentQWidget = None):
        super(QCustomThread, self).__init__(parentQWidget)
        self.wasCanceled = False

    def run (self):
        # Simulate data load estimation
        numberOfprogress = 100
        self.startLoad.emit(numberOfprogress)
        for progress in range(numberOfprogress + 1):
            # Delay
            time.sleep(0.1)
            if not self.wasCanceled:
                self.progressLoad.emit(progress)
            else:
                break
        self.statusLoad.emit(True if progress == numberOfprogress else False)
        self.exit(0)

    def cancel (self):
        self.wasCanceled = True

class QCustomMainWindow (QtGui.QMainWindow):
    def __init__ (self):
        super(QCustomMainWindow, self).__init__()
        # Create action with QPushButton
        self.startQPushButton = QtGui.QPushButton('START')
        self.startQPushButton.released.connect(self.startWork)
        self.setCentralWidget(self.startQPushButton)
        # Create QProgressDialog
        self.loadingQProgressDialog = QtGui.QProgressDialog(self)
        self.loadingQProgressDialog.setLabelText('Loading')
        self.loadingQProgressDialog.setCancelButtonText('Cancel')
        self.loadingQProgressDialog.setWindowModality(QtCore.Qt.WindowModal)

    def startWork (self):
        myQCustomThread = QCustomThread(self)
        def startLoadCallBack (numberOfprogress):
            self.loadingQProgressDialog.setMinimum(0)
            self.loadingQProgressDialog.setMaximum(numberOfprogress)
            self.loadingQProgressDialog.show()
        def progressLoadCallBack (progress):
            self.loadingQProgressDialog.setValue(progress)
        def statusLoadCallBack (flag):
            print 'SUCCESSFUL' if flag else 'FAILED'
        myQCustomThread.startLoad.connect(startLoadCallBack)
        myQCustomThread.progressLoad.connect(progressLoadCallBack)
        myQCustomThread.statusLoad.connect(statusLoadCallBack)
        self.loadingQProgressDialog.canceled.connect(myQCustomThread.cancel)
        myQCustomThread.start()

myQApplication = QtGui.QApplication(sys.argv)
myQCustomMainWindow = QCustomMainWindow()
myQCustomMainWindow.show()
sys.exit(myQApplication.exec_())

想了解更多关于 QtCore.QThread 的信息(建议阅读,以便理解其工作原理)

撰写回答