如何将QThread线程中的列表对象发送到UI的主线程?

时间:2015-11-08 21:02:50

标签: multithreading python-3.x pyside qthread

我编写了这个示例代码,试图找出如何在后台线程和主线程之间进行通信。据我了解,一个线程不能简单地与UI或不同线程中存在的变量进行交互。

我想抓住列表'数据'在后台线程中,然后将其显示在< lbl2'在UI中。如果该程序按原样运行,它将在命令行上打印我想要的结果。

Data received in background thread = [1, 2, 3, 4, 5]

Q1:从后台线程到主线程发送数据(如列表或字符串)的正确方法是什么?

Q2:我将如何开始在示例代码中实现它?

#!/usr/bin/env python3.4
from PySide.QtGui import QPushButton, QApplication, QWidget, QLabel
from PySide.QtCore import QThread, QCoreApplication
import queue
import sys


class Gui(QWidget):
    def __init__(self):
        super(Gui, self).__init__()
        self.initUI()

    def initUI(self):
        lbl1 = QLabel('Data Recieved =', self)
        lbl2 = QLabel('None', self)
        lbl2.move(85, 0)
        lbl2.resize(100, 15)
        qbtn = QPushButton('Quit', self)
        qbtn.clicked.connect(QCoreApplication.instance().quit)
        qbtn.move(0, 20)
        btn = QPushButton('Get Summary', self)
        btn.move(100, 20)
        btn.clicked.connect(lambda: bgThread.summary())
        self.setGeometry(300, 300, 200, 50)
        self.setWindowTitle('Thread Communication Example')
        self.show()


class BackgroundThread(QThread):
    def __init__(self, q, loop_time=1.0/60):
        self.q = q
        self.timeout = loop_time
        super(BackgroundThread, self).__init__()

    def onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def run(self):
        while True:
            try:
               function, args, kwargs =     self.q.get(timeout=self.timeout)
               function(*args, **kwargs)
            except queue.Empty:
                self.idle()

    def idle(self):
        pass

    def _summary(self):
        # Run function which will return a list object
        # data = externalclass.summary()
        # Need to send list:'data' to the main thread.
        data = [1, 2, 3, 4, 5]
        print('Data received in background thread =', data)

    def summary(self):
        self.onThread(self._summary)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # Setup background thread
    request_queue = queue.Queue()
    bgThread = BackgroundThread(request_queue)
    bgThread.start()
    # Setup Gui
    ui = Gui()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:2)

您可以定义一个自定义信号,可以跨线程安全地发出:

from PySide.QtCore import Signal

class Gui(QWidget):
    def initUI(self):
        ...
        bgThread.dataReceived.connect(lambda data: lbl2.setText(str(data)))

class BackgroundThread(QThread):
    dataReceived = Signal(list)
    ...

    def _summary(self):
        ...
        self.dataReceived.emit(data)