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?