我一直试图找到一种同时运行和更新多个进度条的方法,但到目前为止,我运气不好。我想我还需要一个que / run / reset系统才能工作。
有什么想法吗?我一直在玩QThreadPool和QRunnable,但没有成功。
**更新:根据this精彩文章更新了代码。它似乎有效,但存在许多问题:
我收到警告:QObject :: startTimer:无法从其他线程启动计时器
一旦我更改了execute_this_fn函数中的更新频率(如更新1,2,3等),整个事情就会崩溃。
我希望能够将进度条的数量限制为3.如果我点击开始按钮超过三次,则应该对它们进行评估。
from PySide.QtGui import *
from PySide.QtCore import *
import time
import traceback, sys
class WorkerSignals(QObject):
finished = Signal()
error = Signal(tuple)
result = Signal(object)
progress = Signal(int)
class Worker(QRunnable):
def __init__(self, fn, bar, *args, **kwargs):
super(Worker, self).__init__()
self.fn = fn
self.bar = bar
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
# Add the callback to our kwargs
kwargs['progress_callback'] = self.signals.progress
@Slot()
def run(self):
# Retrieve args/kwargs here; and fire processing using them
try:
result = self.fn(self.bar, *self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result) # Return the result of the processing
finally:
self.signals.finished.emit() # Done
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.counter = 0
self.layout = QVBoxLayout()
b = QPushButton("Start thread")
b.pressed.connect(self.start_me)
self.layout.addWidget(b)
w = QWidget()
w.setLayout(self.layout)
self.setCentralWidget(w)
self.show()
self.threadpool = QThreadPool()
print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
def progress_fn(self, n):
print("%d%% done" % n)
def execute_this_fn(self, bar, progress_callback):
for n in range(0, 5):
time.sleep(1)
calc = n*100/4
progress_callback.emit(calc)
bar.setValue(calc)
return "Done."
def print_output(self, s):
print(s)
def thread_complete(self):
print("THREAD COMPLETE!")
def start_me(self):
# Pass the function to execute
xx = self.progress_bar = QProgressBar()
self.layout.addWidget(xx)
worker = Worker(self.execute_this_fn, xx) # Any other args, kwargs are passed to the run function
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
worker.signals.progress.connect(self.progress_fn)
# Execute
self.threadpool.start(worker)
app = QApplication([])
window = MainWindow()
app.exec_()
答案 0 :(得分:0)
使用this作为基础。
from PySide import QtCore
from PySide import QtGui
import sys
import time
import random
class WorkerSignals(QtCore.QObject):
finished = QtCore.Signal()
error = QtCore.Signal(tuple)
result = QtCore.Signal(object)
progress = QtCore.Signal(list)
class Worker(QtCore.QRunnable):
def __init__(self, num, bar):
super(Worker, self).__init__()
self.num = num
self.bar = bar
self.signals = WorkerSignals()
def run(self):
try:
for i in range(1, 101):
self.signals.progress.emit([self.bar, i])
sleep_time = random.uniform(0.01, 0.3)
time.sleep(sleep_time)
except Exception as e:
print "Quit thread {0}".format(self.num)
return
class Tasks(QtGui.QWidget):
def __init__(self):
super(Tasks, self).__init__()
self.pool = QtCore.QThreadPool.globalInstance()
self.pool.setMaxThreadCount(5)
self.layout = QtGui.QVBoxLayout()
self.btn = QtGui.QPushButton("start")
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
self.btn.clicked.connect(self.start_me)
def start_me(self):
for task in range(10):
xx = QtGui.QProgressBar()
self.layout.addWidget(xx)
self.worker = Worker(task, xx)
self.worker.signals.progress.connect(self.setProgress)
self.pool.start(self.worker)
#self.pool.waitForDone()
def setProgress(self, l):
bar, num = l
bar.setValue(num)
#print l
def main():
app = QtGui.QApplication(sys.argv)
panel = Tasks()
panel.show()
app.exec_()
if __name__ == '__main__':
main()