如何在 class init 期间初始化大数据时显示进度条

How to display progress bar while initializing large data during class init

我正在使用 PyQt5。 在下面的代码中 MainWindow.__init__ 期间,我想初始化一些需要很长时间(例如 20 秒)的大数据(参见 MainWindow.initData)。在那段时间里,我想显示一个进度条。直到 app.exec_() 开始执行后才能显示进度条,因此我无法从 MainWindow.__init__ 中调用 initData。因此,我试图通过发布一个事件 (postEvent) 来执行 initData,该事件将导致 initData 在 app.exec_ 执行时执行。我查看了 Whosebug 中的一些示例并得出了以下代码。确实发布了事件并调用了 initData,但是直到 initData 完成后才显示进度条。

请指教如何修改代码,以便在执行initData时显示进度条。谢谢

import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import QEvent

class MyEvent(QEvent):
    idType = QEvent.registerEventType()

    def __init__(self, data):
        QEvent.__init__(self, MyEvent.idType)
        self.data = data
        print("MyEvent.idType ", MyEvent.idType)

    def get_data(self):
        return self.data

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle("My MainWindow")
        self.qProgressBar = QtWidgets.QProgressBar(self)
        self.qProgressBar.setGeometry(100, 100, 200, 30)

        self.label = QtWidgets.QLabel("Hello", self)
        self.label.setGeometry(50, 50, 200, 20)

        tempEvent = MyEvent("12345")
        QtWidgets.QApplication.postEvent(self, tempEvent)

    def initData(self):
        # To demonstrate, do something that takes a long time (for example
        # 20 seconds) and update progress bar.
        print("begin initData")
        loop = 10000
        for i in range(loop):
            self.qProgressBar.setValue(int((i+1)/loop*100))
            for j in range(loop):
                temp = i + j

    def customEvent(self, event):
        print("customEvent:", event.type())
        if (event.type() == MyEvent.idType):
            self.label.setText("Received : {0}".format(event.get_data()))
            self.initData()
    
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    screen = QtWidgets.QDesktopWidget().screenGeometry()
    w.setGeometry(screen.width()//2-200, screen.height()//2-200, 400, 400) # x, y, Width, Height
    w.show()
    
    sys.exit(app.exec_())

谢谢音乐家。这是有效的最终结果!

import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import QObject, QThread, pyqtSignal
from time import sleep

class Worker_InitData(QObject):
    finished = pyqtSignal()
    progress = pyqtSignal(int)

    def run(self):
        """Long-running task."""
        for i in range(10):
            sleep(1)
            self.progress.emit(i)
        self.finished.emit()

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle("My MainWindow")
        self.qProgressBar = QtWidgets.QProgressBar(self)
        self.qProgressBar.setGeometry(100, 100, 200, 30)

        self.label = QtWidgets.QLabel("Hello", self)
        self.label.setGeometry(50, 50, 200, 20)

        self.initData()

    def reportProgress(self, i):
        self.qProgressBar.setValue(int((i+1)/10*100))
    
    def initData(self):
        # Step 2: Create a QThread object
        self.thread = QThread()
        # Step 3: Create a worker object
        self.worker = Worker_InitData()
        # Step 4: Move worker to the thread
        self.worker.moveToThread(self.thread)
        # Step 5: Connect signals and slots
        self.thread.started.connect(self.worker.run)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.progress.connect(self.reportProgress)
        # Step 6: Start the thread
        self.thread.start()
   
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    screen = QtWidgets.QDesktopWidget().screenGeometry()
    w.setGeometry(screen.width()//2-200, screen.height()//2-200, 400, 400) # x, y, Width, Height
    w.show()
    
    sys.exit(app.exec_())