-
-
Save HeaTTheatR/3fad6402bdbb3ef2935fdd22628f7b56 to your computer and use it in GitHub Desktop.
async/await in Kivy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| __all__ = ('start', 'sleep', 'event', ) | |
| import types | |
| from functools import partial | |
| from collections import namedtuple | |
| from kivy.clock import Clock | |
| CallbackParameter = namedtuple('CallbackParameter', ('args', 'kwargs', )) | |
| def start(coro): | |
| def step(*args, **kwargs): | |
| try: | |
| coro.send(CallbackParameter(args, kwargs))(step) | |
| except StopIteration: | |
| pass | |
| try: | |
| coro.send(None)(step) | |
| except StopIteration: | |
| pass | |
| @types.coroutine | |
| def sleep(duration): | |
| # The partial() here looks meaningless. But this is needed in order | |
| # to avoid weak reference | |
| param = yield lambda step_coro: Clock.schedule_once( | |
| partial(step_coro), duration) | |
| return param.args[0] | |
| class event: | |
| def __init__(self, ed, name): | |
| self.bind_id = None | |
| self.ed = ed | |
| self.name = name | |
| def bind(self, step_coro): | |
| self.bind_id = bind_id = self.ed.fbind(self.name, self.callback) | |
| assert bind_id > 0 # check if binding succeeded | |
| self.step_coro = step_coro | |
| def callback(self, *args, **kwargs): | |
| self.parameter = CallbackParameter(args, kwargs) | |
| ed = self.ed | |
| ed.unbind_uid(self.name, self.bind_id) | |
| self.step_coro() | |
| def __await__(self): | |
| yield self.bind | |
| return self.parameter |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| from kivy.app import App | |
| from kivy.uix.label import Label | |
| from kivy.utils import get_color_from_hex | |
| import asynckivy as ak | |
| class TestApp(App): | |
| def build(self): | |
| return Label(text='Hello', markup=True, font_size='80sp', | |
| outline_width=2, | |
| outline_color=get_color_from_hex('#FFFFFF'), | |
| color=get_color_from_hex('#000000'), | |
| ) | |
| def on_start(self): | |
| async def animate(label): | |
| await ak.sleep(1.5) | |
| while True: | |
| label.outline_color = get_color_from_hex('#FFFFFF') | |
| label.text = 'Do' | |
| await ak.sleep(.5) | |
| label.text = 'you' | |
| await ak.sleep(.5) | |
| label.text = 'like' | |
| await ak.sleep(.5) | |
| label.text = 'Kivy?' | |
| await ak.sleep(2) | |
| label.outline_color = get_color_from_hex('#FF5555') | |
| label.text = 'Answer me!' | |
| await ak.sleep(2) | |
| label.outline_color = get_color_from_hex('#FFFF00') | |
| label.text = 'Left-click to replay' | |
| while True: | |
| args, kwargs = await ak.event(label, 'on_touch_down') | |
| touch = args[1] | |
| if touch.button == 'left': | |
| break | |
| ak.start(animate(self.root)) | |
| if __name__ == '__main__': | |
| TestApp().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this, found it extremely helpful in understanding how Kivy's Clock works.