当另一个线程更新其文本时,不会呈现pyqt QLabel

时间:2016-06-12 04:45:59

标签: python pyqt pyqt5

我有一个基于PyQt5的GUI程序,它不断接收消息。 GUI有一个QLabel显示收到的消息数,一个QThread试图在run()中的无限循环中接收消息和更新计数器。这是代码:

class ReceiveThread(QtCore.QThread):
    def __init__(self, parent, dialog, config):
        super(BufRecvThread, self).__init__(parent)
        #here dialog is the QDialog which contains the QLabel showing the message counter
        self.dialog=dialog             
        self.toStop=False

    def run(self):
        bufRecvCnt=0
        while not self.toStop:
            recv_buff=sock.recvMessage()
            bufRecvCnt=bufRecvCnt+1
            #self.dialog.lbBufRecvCnt is the QLabel showing the message counter
            self.dialog.lbBufRecvCnt.setText(str(bufRecvCnt))
            QApplication.processEvents() #this statement has no effect

但是,大多数情况下,我发现GU​​I中的QLabel没有正确呈现计数器,比如,ReceiveThread已经收到10000条消息并且在sock.recvMessage()处阻塞,QLabel仍然显示" 500"直到我手动调整GUI大小,导致GUI重新渲染。

我尝试了这个线程pyqt QtGraphicsView does not get updated within loop的建议,并将QApplication.processEvents()添加到循环中,但仍然不起作用。

那么,从另一个线程直接更新 GUI是否合适? PyQt - Modify GUI from another thread建议发出信号。因为我不熟悉信号和插槽,我应该使用QLabel的预定义信号,或者我可以定义我需要的任何信号,只要相应的插槽将使用setText()更新QLabel的文本。

1 个答案:

答案 0 :(得分:1)

只有主GUI线程才能更新GUI。您不应该直接与主线程之外的GUI对象进行交互。如果要与工作线程的主线程进行通信,则需要使用SignalsSlots

class Dialog(QtGui.QDialog):

    def __init__(self, parent):
        super(Dialog, self).__init__(parent)
        ...

        self.thread = ReceiveThread(self)
        self.thread.message_received.connect(self.handle_message)

    @QtCore.pyqtSlot(str)
    def handle_message(self, message):
        self.lbBufRecvCnt.setText(message)


class ReceiveThread(QtCore.QThread):

    message_received = QtCore.pyqtSignal(str)

    def __init__(self, parent, config):
        super(ReceiveThread, self).__init__(parent)           
        self.toStop = False

    def run(self):
        bufRecvCnt=0
        while not self.toStop:
            recv_buff = sock.recvMessage()
            bufRecvCnt = bufRecvCnt + 1
            self.message_received.emit(str(bufRecvCnt))