如何在 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_())
我正在使用 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_())