将信号从多个工作线程发送到GUI线程

时间:2016-03-23 20:37:52

标签: python multithreading pyqt4 signals-slots

我有一个带有24个文本框的gui,我想为每个文本框创建一个帖子,并用来自它各自线程的信息更新文本框。

我卡住的地方正在接收来自所有线程的更新gui的信号。

代码:

#!/usr/bin/python
# Standard Lib
import logging
import os
import sys
import time
# Third Party
from PyQt4 import QtGui
from PyQt4 import QtCore
# Local Kung Fu
from bin import serial_lib, logger, get_args, utils
from bin.assets.test_suite_gui_form import Ui_MainWindow

class Tester(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
        self.color = "RED"
        self.status = "Disconnected"

    def __del__(self):
        self.wait()

    def run(self):
        self.emit(QtCore.SIGNAL('update(QString)'), "color={} status={}".format(self.color, self.status))
        return

class TestSuiteGUI(QtGui.QMainWindow):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        # Init class from template
        self.ui = Ui_MainWindow()
        # Get list of com ports to populate app on init
        self.com_ports_list = serial_lib.get_com_ports()
        # Build UI
        self.ui.setupUi(self)
        # Update Labels with COM Ports, where possible, filtered by drivers
        self.update_comm_fields(self.com_ports_list)
        for num, com_port_chunk in zip(range(1,25), self.com_ports_list):
            tester_thread = Tester(com_port_chunk, num)
            tester_thread.start()

    def update_comm_fields(self, com_ports_list):
        for num, port, in zip(range(1, 25), range(0, 24)):
            label = getattr(self.ui, 'com_{}'.format(num))
            label.setText("COM Port: {}".format(com_ports_list[port]["COM"]))

if __name__ == "__main__":
    # Grab args from CLI if necessary
    args = get_args.get_args()
    # Log file
    log_file = os.path.join(utils.app_path, "log", "log.txt")
    # Get Logger
    logger.get_logger(log_file, verbose=True)
    # Init App and display
    app = QtGui.QApplication(sys.argv)
    test_suite = TestSuiteGUI()
    test_suite.show()
    # Close app only when window is closed.
    sys.exit(app.exec_())

这是正确的做法吗?我尝试使用QRunnable和一个线程池,但在某个地方读取信号不能使用它。我应该尝试使用python的多线程库作为最后的手段,还是基于事件的系统,因为我需要传递的只是一个字符串和布尔值?

1 个答案:

答案 0 :(得分:1)

您应该定义并发出如下信号:

class Tester(QtCore.QThread):
    updateText = QtCore.pyqtSignal(str)
    ...    
    def run(self):
        self.updateText.emit("color={} status={}".format(self.color, self.status))

然后你可以连接到这样的信号:

class TestSuiteGUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        ...
        # keep a reference to the threads
        self._threads = []
        for num, com_port_chunk in zip(range(1,25), self.com_ports_list):
            tester_thread = Tester(com_port_chunk, num)
            # get a reference to the associated textbox somehow...
            textbox = get_the_textbox()
            tester_thread.updateText.connect(textbox.setText)
            tester_thread.start()
            self._threads.append(tester_thread)

显然,这有点粗略,因为实际测试你的例子是不可能的。