我有一个基于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
但是,大多数情况下,我发现GUI中的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的文本。
答案 0 :(得分:1)
只有主GUI线程才能更新GUI。您不应该直接与主线程之外的GUI对象进行交互。如果要与工作线程的主线程进行通信,则需要使用Signals
和Slots
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))