Related question here
I've discovered a slave property for the runTouchApp function that prevents the Kivy's event loop from running and forces to update it from somewhere else.
Here's a part of app.py where that property is used:
# 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()
Here, if the app is not being run in slave mode, we have two choices on how to run the mainloop.
The first one, _run_mainloop() function works pretty straight-forward - it simply calls the EventLoop.run(), which in turn infinitely calls EventLoop.idle().
That could lead us to believe that to keep the GUI running, we only need to call idle.
But then there's the second option, which calls the kivy.core.window.WindowSDL's method mainloop.
That method works by calling another method, the _mainloop and this is where it gets interesting. The definition of said method is huge and it handles all sorts of events.
So okay, I ran my app in slave mode:
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()
Now, if I put this in the start_event method (by expectations):
def start_event(self):
while True:
EventLoop.idle()
Guess what, the app doesn't respond to touch events and freezes.
So I tried to call the Window's mainloop instead:
def start_event(self):
EventLoop.window.mainloop()
And suddenly everything started working normally again. But the problem here is that such a call blocks forever, as it is an infinite loop, so there's no one-time update call like EventLoop.idle
How to keep the app running using such one-time calls?