如何重复使用带有响应式进度条的 Qthread
How to repeating using Qthread with responsive progressbar
当使用 python pyqt 时,我制作了一个 Qprogressbar,并使用 Q 线程更新了数字。下面显示的代码第一次是成功的,但是它会在执行另一个 运行.
时崩溃
这是针对 Python PyQt5,在 Python 3.5 系统中。我已经尝试将进度条重置为 0 但它似乎不正确
这是我点击加载文件按钮后的调用函数,加载文件按钮和进度条位于QtWidgets.Qmainwindows
loading_event_name = QtWidgets.QFileDialog.getOpenFileNames(self, 'CSV File', 'C:\', '*.csv')
self.loading_progress_bar.reset()
self.loading_thread = QThread()
self.loading_worker = Load_Task_Thread()
self.loading_worker.moveToThread(self.loading_thread)
self.loading_thread.started.connect(self.loading_worker.run)
self.loading_thread.start()
self.loading_worker.Load_taskFinished.connect(self.Load_onFinished)
self.loading_worker.Loading_progressChanged.connect(self.loading_progress_bar.setValue, Qt.QueuedConnection)'''
第一个加载文件线程可以正常工作,但是如果我想加载新文件,下次单击时,软件会崩溃,线程没有更新,进度条没有像第一次那样更新数字,并且自那以后保持为零我重置了它。在调试模式下,我也不能向进度条发出任何数字:
class Load_Task_Thread(QThread):
Load_taskFinished = pyqtSignal()
Loading_progressChanged = pyqtSignal(int)
def run(self):
progress = 0
for file_name_num in range(len(loading_event[0])):
progress = 90 * file_name_num/len(loading_event_name[0])
self.Loading_progressChanged.emit(progress)
1+1.....
self.Loading_progressChanged.emit(100)
self.Load_taskFinished.emit()
我希望无论点击多少次选择新文件,进度条都能更新。或者有没有其他简单的方法可以显示进度条来显示加载过程。
您可能还有其他错误,但从您提供的代码中我观察到以下错误:
您已经创建了一个 QThread (Load_Task_Thread) 并将其移动到另一个 QThread,这是不必要的,因为 Load_Task_Thread 是一个 QObject 就足够了。
不需要每次启动进程都创建一个QThread,因为一个QObject存在于一个线程中就足够了。
考虑到上述情况,我实现了以下示例:
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
class Load_Task_Worker(QtCore.QObject):
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
progressChanged = QtCore.pyqtSignal(int)
@QtCore.pyqtSlot(list)
def run(self, filenames):
total = len(filenames)
self.started.emit()
self.progressChanged.emit(0)
for i, filename in enumerate(filenames, 1):
# start process
# ...
# end process
progress = 100 * i // total
self.progressChanged.emit(progress)
self.finished.emit()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.button = QtWidgets.QPushButton("Start Task")
self.loading_progress_bar = QtWidgets.QProgressBar()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.button)
lay.addWidget(self.loading_progress_bar)
thread = QtCore.QThread(self)
thread.start()
self.worker = Load_Task_Worker()
self.worker.moveToThread(thread)
self.button.clicked.connect(self.onClicked)
self.worker.progressChanged.connect(self.loading_progress_bar.setValue)
self.worker.finished.connect(self.onFinished)
@QtCore.pyqtSlot()
def onFinished(self):
self.button.setEnabled(True)
@QtCore.pyqtSlot()
def onClicked(self):
filenames, _ = QtWidgets.QFileDialog.getOpenFileNames(
self, "CSV File", "C:\", "*.csv"
)
if filenames:
self.button.setEnabled(False)
self.loading_progress_bar.reset()
wrapper = partial(self.worker.run, filenames)
QtCore.QTimer.singleShot(0, wrapper)
else:
print("not selected files")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
当使用 python pyqt 时,我制作了一个 Qprogressbar,并使用 Q 线程更新了数字。下面显示的代码第一次是成功的,但是它会在执行另一个 运行.
时崩溃这是针对 Python PyQt5,在 Python 3.5 系统中。我已经尝试将进度条重置为 0 但它似乎不正确
这是我点击加载文件按钮后的调用函数,加载文件按钮和进度条位于QtWidgets.Qmainwindows
loading_event_name = QtWidgets.QFileDialog.getOpenFileNames(self, 'CSV File', 'C:\', '*.csv')
self.loading_progress_bar.reset()
self.loading_thread = QThread()
self.loading_worker = Load_Task_Thread()
self.loading_worker.moveToThread(self.loading_thread)
self.loading_thread.started.connect(self.loading_worker.run)
self.loading_thread.start()
self.loading_worker.Load_taskFinished.connect(self.Load_onFinished)
self.loading_worker.Loading_progressChanged.connect(self.loading_progress_bar.setValue, Qt.QueuedConnection)'''
第一个加载文件线程可以正常工作,但是如果我想加载新文件,下次单击时,软件会崩溃,线程没有更新,进度条没有像第一次那样更新数字,并且自那以后保持为零我重置了它。在调试模式下,我也不能向进度条发出任何数字:
class Load_Task_Thread(QThread):
Load_taskFinished = pyqtSignal()
Loading_progressChanged = pyqtSignal(int)
def run(self):
progress = 0
for file_name_num in range(len(loading_event[0])):
progress = 90 * file_name_num/len(loading_event_name[0])
self.Loading_progressChanged.emit(progress)
1+1.....
self.Loading_progressChanged.emit(100)
self.Load_taskFinished.emit()
我希望无论点击多少次选择新文件,进度条都能更新。或者有没有其他简单的方法可以显示进度条来显示加载过程。
您可能还有其他错误,但从您提供的代码中我观察到以下错误:
您已经创建了一个 QThread (Load_Task_Thread) 并将其移动到另一个 QThread,这是不必要的,因为 Load_Task_Thread 是一个 QObject 就足够了。
不需要每次启动进程都创建一个QThread,因为一个QObject存在于一个线程中就足够了。
考虑到上述情况,我实现了以下示例:
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
class Load_Task_Worker(QtCore.QObject):
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
progressChanged = QtCore.pyqtSignal(int)
@QtCore.pyqtSlot(list)
def run(self, filenames):
total = len(filenames)
self.started.emit()
self.progressChanged.emit(0)
for i, filename in enumerate(filenames, 1):
# start process
# ...
# end process
progress = 100 * i // total
self.progressChanged.emit(progress)
self.finished.emit()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.button = QtWidgets.QPushButton("Start Task")
self.loading_progress_bar = QtWidgets.QProgressBar()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.button)
lay.addWidget(self.loading_progress_bar)
thread = QtCore.QThread(self)
thread.start()
self.worker = Load_Task_Worker()
self.worker.moveToThread(thread)
self.button.clicked.connect(self.onClicked)
self.worker.progressChanged.connect(self.loading_progress_bar.setValue)
self.worker.finished.connect(self.onFinished)
@QtCore.pyqtSlot()
def onFinished(self):
self.button.setEnabled(True)
@QtCore.pyqtSlot()
def onClicked(self):
filenames, _ = QtWidgets.QFileDialog.getOpenFileNames(
self, "CSV File", "C:\", "*.csv"
)
if filenames:
self.button.setEnabled(False)
self.loading_progress_bar.reset()
wrapper = partial(self.worker.run, filenames)
QtCore.QTimer.singleShot(0, wrapper)
else:
print("not selected files")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())