Skip to content

asyncgui/asynckivy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

a64e31f · Jul 25, 2020
Jun 6, 2020
Jul 23, 2020
Jul 6, 2020
May 5, 2020
Jul 23, 2020
Jun 6, 2020
Aug 17, 2019
Mar 10, 2020
Jul 6, 2020
Jul 6, 2020
Jun 6, 2020
Jul 25, 2020
Jul 25, 2020
Jul 6, 2020

Repository files navigation

AsyncKivy

Youtube
日本語doc

Installation

# stable version
pip install asynckivy
# development version
pip install git+https://github.com/gottadiveintopython/asynckivy.git@master#egg=asynckivy

Usage

import asynckivy as ak
from asynckivy.process_and_thread import \
    thread as ak_thread, process as ak_process

async def some_task(button):
    # wait for 1sec
    await ak.sleep(1)
    
    # wait until a button is pressed
    await ak.event(button, 'on_press')

    # wait until 'button.x' changes
    __, x = await ak.event(button, 'x')
    print(f'button.x is now {x}')

    # wait until 'button.x' becomes greater than 100
    if button.x <= 100:
        __, x = await ak.event(button, 'x', filter=lambda __, x: x>100)
        print(f'button.x is now {x}')

    # create a new thread, run a function on it, then
    # wait for the completion of that thread
    r = await ak_thread(some_heavy_task)
    print(f"result of 'some_heavy_task()': {r}")

    # wait for the completion of subprocess
    import subprocess
    p = subprocess.Popen(...)
    returncode = await ak_process(p)

    # wait until EITHER a button is pressed OR 5sec passes
    tasks = await ak.or_(
        ak.event(button, 'on_press'),
        ak.sleep(5),
    )
    print("The button was pressed" if tasks[0].done else "5sec passed")

    # wait until BOTH a button is pressed AND 5sec passes"
    tasks = await ak.and_(
        ak.event(button, 'on_press'),
        ak.sleep(5),
    )

    # wait for the completion of an animation
    await ak.animate(button, width=200, t='in_out_quad', d=.5)
ak.start(some_task(some_button))

touch handling

You can easily handle on_touch_xxx events via asynckivy.rest_of_touch_moves().

import asynckivy as ak

class Painter(RelativeLayout):
    def on_touch_down(self, touch):
        if self.collide_point(*touch.opos):
            ak.start(self.draw_rect(touch))
            return True
    
    async def draw_rect(self, touch):
        from kivy.graphics import Line, Color, Rectangle
        from kivy.utils import get_random_color
        with self.canvas:
            Color(*get_random_color())
            line = Line(width=2)
        ox, oy = self.to_local(*touch.opos)
        async for __ in ak.rest_of_touch_moves(self, touch):
            # This part is iterated everytime 'on_touch_move' is fired.
            # Don't await anything during this iteration.
            x, y = self.to_local(*touch.pos)
            min_x = min(x, ox)
            min_y = min(y, oy)
            max_x = max(x, ox)
            max_y = max(y, oy)
            line.rectangle = [min_x, min_y, max_x - min_x, max_y - min_y]
        # If you want to do something when 'on_touch_up' is fired, do it here.
        do_something_on_touch_up()

synchronization primitive

There is a Trio's Event equivalent.

import asynckivy as ak

async def task_A(e):
    print('A1')
    await e.wait()
    print('A2')
async def task_B(e):
    print('B1')
    await e.wait()
    print('B2')

e = ak.Event()
ak.start(task_A(e))
# A1
ak.start(task_B(e))
# B1
e.set()
# A2
# B2

Test Environment

  • CPython 3.7.1 + Kivy 1.11.1