PySide - 更新多个进度条

时间:2017-10-01 21:55:49

标签: python pyqt pyside pyside2

我一直试图找到一种同时运行和更新多个进度条的方法,但到目前为止,我运气不好。我想我还需要一个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_()

1 个答案:

答案 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()