我有一个python qt5应用程序,该应用程序在另一个线程中启动龙卷风插座客户端。我想知道的是,每当我在Tornado的Websocket.read_message()中获得结果时,如何将该值传递给QT5 GUI标签。
这是Main.py,它在新线程中启动QT5 GUI应用程序和龙卷风Websocket。
import sys
import threading
from PyQt5.QtWidgets import QApplication
from app.ui.components import MainWindow
from app.client import Client
from config import SERVER_URL
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
sys.exit(app.exec_())
if __name__ == '__main__':
client = Client("ws://{0}/socket".format(SERVER_URL), 5)
thread = threading.Thread(target=lambda : client.ioloop.start())
thread.setDaemon(True)
thread.start()
main()
这是client.py
from tornado import gen
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.websocket import websocket_connect
class Client(object):
def __init__(self, url, timeout):
self.url = url
self.timeout = timeout
self.ioloop = IOLoop.instance()
self.ws = None
self.connect()
self.periodic_callback = PeriodicCallback(self.keep_alive, 20000, io_loop=self.ioloop)
@gen.coroutine
def connect(self):
try:
self.ws = yield websocket_connect(self.url)
self.periodic_callback.start()
except Exception as e:
pass
else:
self.run()
@gen.coroutine
def run(self):
while True:
msg = yield self.ws.read_message()
if msg is None:
self.ws = None
break
print("Received: {0}".format(msg)) # HOW TO PASS msg to GUI LABEL WHENEVER IT RECEIVES A NEW VALUE
def keep_alive(self):
if self.ws is None:
self.connect()
else:
self.ws.write_message("Hello from client")
龙卷风线程可以从原始线程中访问内存中的对象。因此,一个非常简单的解决方案是将QApplication
或其他对象从QT应用程序传递到客户端对象。然后,当您收到消息时,您可以调用QT对象上的任何方法。
但是,很明显这将安全起作用。QT对象可能无法设计为从两个不同的线程访问。在不知道要使用类的情况下,您不应该假设它是 thread-safe 。因此,简单的解决方案可能意味着同时某些QT代码在主线程上运行,龙卷风线程调用了一些QT代码,该代码改变了QT对象的状态。另一个代码没想到会发生变化,因此您会崩溃或其他故障。
您可能会发现QT库是旨在应对的。但是在任何情况下都是更好的方法-A 生产者 - 消费者队列。
这意味着您有一个队列对象,该对象在线程之间共享。这可以是您已经使用的threading
模块的threading.Queue
。每次收到WebSocket时,您都会在队列上进行put
。这可能是任何python对象 - 如果需要的话,只是消息字符串,或者如果需要的话,则可以进行一些自定义对象。
然后,在另一个线程上,您有一个循环,该循环仅从队列中读取,并在每次收到消息时调用QT。
编辑 - QT可能可以处理此
我对QT了解不多。但是,大多数窗口系统实际上都有自己的事件队列,在此处管理点击,按键按下等。如果在此事件队列上处理了QT更新某些内容,则可能意味着它们是线程安全的。这是因为您从龙卷风线程中调用的函数并不能直接更改GUI,而是在QT到达QT时只会在要处理的队列中添加一些东西。
我快速看一些关于QT的东西,看来这可能是QT的工作方式,您应该从龙卷风线程中找到它,而无需实现自己的队列。