首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在从模式下运行Kivy EventLoop?

如何在从模式下运行Kivy EventLoop?
EN

Stack Overflow用户
提问于 2016-12-10 15:45:09
回答 1查看 1K关注 0票数 2

相关问题here

我发现了一个slave属性,用于runTouchApp函数,它阻止Kivy的事件循环运行,并强制从其他地方更新它。

下面是使用该属性的app.py的一部分:

代码语言:javascript
复制
# we are in a slave mode, don't do dispatching.
if slave:
    return

try:
    if EventLoop.window is None:
        _run_mainloop()
    else:
        EventLoop.window.mainloop()
finally:
    stopTouchApp()

在这里,如果应用程序没有在从模式下运行,我们有两个关于如何运行主循环的选择。

第一个是_run_mainloop()函数,它简单地调用EventLoop.run(),然后无限地调用EventLoop.idle()

这可能让我们相信,为了使GUI继续运行,我们只需调用idle

但是还有第二个选项,它调用kivy.core.window.WindowSDL的方法mainloop

该方法通过调用另一个方法_mainloop来工作,这就是它变得有趣的地方。该方法的定义是huge,它处理各种事件。

好吧,我在从模式下运行我的应用程序:

代码语言:javascript
复制
class TestApp(App):
    def start_event(self):
        pass

    def build(self):
        return Button(text = "hello")

    def run(self):
        # This definition is copied from the superclass 
        # except for the start_event call and slave set to True

        if not self.built:
            self.load_config()
            self.load_kv(filename=self.kv_file)
            root = self.build()
            if root:
                self.root = root

        if self.root:
            Window.add_widget(self.root)

        window = EventLoop.window
        if window:
            self._app_window = window
            window.set_title(self.get_application_name())
            icon = self.get_application_icon()
            if icon:
                window.set_icon(icon)
            self._install_settings_keys(window)


        self.dispatch('on_start')
        runTouchApp(slave = True)
        self.start_event()  # Here we start updating
        self.stop()

现在,如果我将其放在start_event方法中(根据预期):

代码语言:javascript
复制
def start_event(self):
    while True:
        EventLoop.idle()

你猜怎么着,这个应用程序不响应触摸事件和冻结。

因此,我尝试调用窗口的主循环:

代码语言:javascript
复制
def start_event(self):
    EventLoop.window.mainloop()

突然一切又恢复正常了。但是这里的问题是这样的调用永远阻塞,因为它是一个无限循环,所以没有像EventLoop.idle这样的一次性更新调用。

如何使用这种一次性调用来保持应用程序的运行?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-11 10:33:42

好吧,这就是Python,假设您想要坚持使用WindowSDL提供程序,您可以随时对这个mainloop函数进行猴子修补,这样它就不会是无限的:

代码语言:javascript
复制
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.base import EventLoop

Builder.load_string('''
<MyWidget>:
    Button:
        text: 'test'
        on_press: print('doing my job')
''')

# https://github.com/kivy/kivy/blob/master/kivy/core/window/window_sdl2.py#L630
def mainloop(self):
    # replaced while with if
    if not EventLoop.quit and EventLoop.status == 'started':
        try:
            self._mainloop()
        except EventLoop.BaseException as inst:
            # use exception manager first
            r = EventLoop.ExceptionManager.handle_exception(inst)
            if r == EventLoop.ExceptionManager.RAISE:
                EventLoop.stopTouchApp()
                raise
            else:
                pass


class MyWidget(BoxLayout):
    pass


if __name__ == '__main__':
    from kivy.base import runTouchApp
    runTouchApp(MyWidget(), slave=True)
    # monkey patch
    EventLoop.window.mainloop = mainloop
    while True:
        EventLoop.window.mainloop(EventLoop.window)
        print('do the other stuff')
        if EventLoop.quit:
            break

不过,这真的很麻烦,因此我不建议在生产代码中运行这样的代码。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41077272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档