如何在 Kivy GUI 旁边运行 Tornado 事件循环?
问题描述
我的客户端应用程序使用 Kivy
GUI(Kivy 有自己的事件循环)并使用带有 Tornado
的 WebSocket 协议连接到服务器(Tornado 也有一个事件循环).这就是连接部分是异步的原因.
我希望用户在 Tornado 客户端运行无限异步循环以侦听服务器消息时与 UI 交互.
My client application uses a Kivy
GUI (Kivy has its own event loop) and connects to the server using the WebSocket protocol with Tornado
(Tornado also has an event loop). That's why the connection part is asynchronous.
I want the user to interact with the UI while a Tornado client is running an infinite asynchronous loop of listening for server messages.
以下是一些示例代码:
client_test.py
from tornado.ioloop import IOLoop
from tornado.websocket import websocket_connect
class RequestSender:
url = 'server url here (no scheme)'
async def _connect(self):
self.conn = await websocket_connect('wss://' + self.url, io_loop=self.ioloop)
self.ioloop.add_callback(self._listen)
async def _listen(self):
while True:
print(await self.conn.read_message())
def __init__(self):
self.ioloop = IOLoop.current()
self.ioloop.add_callback(self._connect)
def run(self):
self.ioloop.start()
图形界面
from kivy.app import App
from kivy.uix.label import Label
from client_test import RequestSender
class TestApp(App):
def build(self):
RequestSender().run()
return Label(text = "hello")
TestApp().run()
显然,由于 Tornado 的事件循环已经开始较早,它已经接管了程序流程,现在没有出现 GUI 窗口.
我执行 GUI 文件,在 RequestSender().run()
之后执行挂起,因此 build
永远不会返回.
Apparently, since the Tornado's event loop has started earlier, it has taken over the program flow and now no GUI window appears.
I execute the GUI file and the execution hangs after the RequestSender().run()
, so build
never returns.
搜索此案例几乎没有提供任何信息,除了 thisGoogle 网上论坛帖子.Kivy 的文档仅提及 Twisted.
Searching on this case provided little to no information, except for this Google Groups post. Kivy's documentation only mentions Twisted.
我尝试将 Kivy 事件循环置于从属模式并从 Tornado 的事件循环运行 GUI 更新,但这不起作用,因为显然 Kivy 的事件循环的调用 EventLoop.idle()
不是足以保持 GUI 应用程序运行.
I tried putting the Kivy event loop into slave mode and running GUI updates from Tornado's event loop, but that didn't work because apparently a call EventLoop.idle()
of Kivy's event loop isn't enough to keep the GUI application running.
这里还能做什么?
解决方案
我发现这个问题试图做同样的事情,并选择了两个单独的进程;一个 Kivy GUI 和一个 Tornado(在我的例子中是服务器).我有两个使用 multiprocessing.connection
进行通信,如 this SO answer 中所述
I found this question trying to do the same thing, and opted for two separate processes instead; one Kivy GUI and one Tornado (Server, in my case). I have the two communicate using multiprocessing.connection
as explained well in this SO answer
如果您要在两者之间传递大量而复杂的数据,这可能不太理想,但对于简单的消息来说效果很好.您还可以在没有 UI 的情况下运行,并在单独的计算机上运行 UI.
If you have large and complex data to pass between the two, perhaps this is less than ideal, but for simple messages it works well. You also have the advantage of running without the UI, and running the UI on a separate machine.
相关文章