如何在线程完成后更新小部件

时间:2017-07-02 14:43:45

标签: python multithreading qt pyqt multiprocessing

下面的代码创建一个带有标签和按钮的对话框。 按下按钮可调用onClick函数,该函数将calculate作为任务放入queue触发thread来完成工作。

线程完成后,我想调用dialog.onThreadCompleted方法将计算结果作为参数传递给它。然后,此方法将使用self.label执行的计算结果更新thread。如何实现呢?

enter image description here

import threading
import Queue as Queue
import functools

global queue
queue = Queue.Queue()


class Thread(QThread):
    def __init__(self, parent=None):
        QThread.__init__(self, parent)

    def run(self):
        global queue
        while True:
            partial = queue.get()
            output = partial()
            queue.task_done()


threads = []
thread = Thread()
threads.append(thread)
thread.start()


def calculate(number):
    for i in range(number):
        i += i
    print 'calculate completed. result: %s' % i
    return i


class Dialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setLayout(QVBoxLayout())
        self.label = QLabel(self)
        self.label.setText('This label should display result')
        self.layout().addWidget(self.label)
        button = QPushButton('Start process')
        button.clicked.connect(self.onClick)
        self.layout().addWidget(button)

    def onThreadCompleted(self, result):
        self.label.setText(str(result))

    def onClick(self):
        self.label.setText('Calculation is starting...')
        partial = functools.partial(calculate, number=100000000)
        queue.put(partial)

if __name__ == '__main__':
    app = QApplication([])
    dialog = Dialog()
    dialog.show()
    qApp.exec_()

1 个答案:

答案 0 :(得分:1)

我决定修改您的代码,以便仅使用PyQt(无QueueThread,仅使用QThread)。我希望代码是自我解释的。如果没有,请问:)

from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QDialog
from PyQt4.QtGui import *

import sys

class Thread(QtCore.QObject):
    finished = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        QtCore.QObject.__init__(self, parent)

        self.TheWorker = QtCore.QThread()
        self.moveToThread(self.TheWorker)
        self.TheWorker.start()

        self.number = 0

    def calculate(self):
        num = 10000
        for i in range(num):
            self.number += i
        print 'calculate completed. result: %s' % self.number
        self.finished.emit()

class Dialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        # worker which will do the job or you on different thread
        self.myWorker = Thread()
        # catched signal about finishing the job and calls desired method
        self.myWorker.finished.connect(self.onThreadCompleted)

        self.setLayout(QVBoxLayout())
        self.label = QLabel(self)
        self.label.setText('This label should display result')
        self.layout().addWidget(self.label)
        button = QPushButton('Start process')
        button.clicked.connect(self.myWorker.calculate)
        self.layout().addWidget(button)

    def onThreadCompleted(self):
        self.label.setText(str(self.myWorker.number))

    # to quit the thread properly
    def quitThread(self):
        self.myWorker.TheWorker.quit()
        self.myWorker.TheWorker.wait()

if __name__ == '__main__':
    app = QApplication([])
    dialog = Dialog()
    dialog.show()
    qApp.exec_()
    dialog.quitThread()
    sys.exit()