How can I send a list object from a QThread thread to the UI's main thread?

和自甴很熟 提交于 2019-12-02 11:58:41

问题


I have written this example code to try and figure out how to communicate between a background thread, and the main thread. As I understand it, a thread cannot simply interact with the UI or variables existing in a different thread.

I would like to grab the list 'data' in the background thread, then display it on 'lbl2' in the UI. If this program is run as is, it will print the result I want on the command line.

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

Q1: What is the correct way to send data such as a list or string, from the background thread to the main thread?

Q2: How would I begin to implement that in the example code?

#!/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:


You can define a custom signal, which can be safely emitted across threads:

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)


来源:https://stackoverflow.com/questions/33599011/how-can-i-send-a-list-object-from-a-qthread-thread-to-the-uis-main-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!