Skip to main content

Async library for Tkinter

Project description

AsyncTkinter2

日本語版

asynctkinter2 is an async library that saves you from ugly callback-style code, like most of async libraries do. Let's say you want to do:

  1. print("A")
  2. wait for 1sec
  3. print("B")
  4. wait for a label to be pressed
  5. print("C")

in that order. Your code would look like this:

def what_you_want_to_do(label):
    bind_id = None
    print("A")

    def one_sec_lator(__):
        nonlocal bind_id
        print("B")
        bind_id = label.bind("<ButtonPress>", on_press, "+")
    label.after(1000, one_sec_lator)

    def on_press(event):
        label.unbind("<ButtonPress>", bind_id)
        print("C")

what_you_want_to_do(...)

This is hard to follow. With asynctkinter2, the same logic becomes:

import asynctkinter2 as atk

async def what_you_want_to_do(label):
    print("A")
    await atk.sleep(label, 1000)
    print("B")
    await atk.event(label, "<ButtonPress>")
    print("C")

atk.start(what_you_want_to_do(...))

Installation

Pin the minor version.

pip install "asynctkinter2>=0.1,<0.2"

Example

import tkinter as tk
import asynctkinter2 as atk


def main():
    root = tk.Tk()
    root_task = atk.start(async_main(root))
    root.protocol("WM_DELETE_WINDOW", lambda: (root_task.cancel(), root.destroy()))
    root.mainloop()


async def async_main(root: tk.Tk):
    label = tk.Label(root, text='Hello', font=('', 80))
    label.pack()

    # Waits for 2 seconds to elapse.
    await atk.sleep(root, 2000)

    # Waits for a label to be pressed.
    event = await atk.event(label, "<ButtonPress>")
    print(f"pos: {event.x}, {event.y}")

    # Waits for either 5 seconds to elapse or a label to be pressed.
    # i.e. Waits at most 5 seconds for a label to be pressed.
    tasks = await atk.wait_any(
        atk.sleep(root, 5000),
        atk.event(label, "<ButtonPress>"),
    )
    if tasks[0].finished:
        print("Timeout")
    else:
        event = tasks[1].result
        print(f"Label pressed (pos: {event.x}, {event.y})")

    # Waits for both 5 seconds to elapse and a label to be pressed.
    tasks = await atk.wait_all(
        atk.sleep(root, 5000),
        atk.event(label, "<ButtonPress>"),
    )

    # Performs an HTTP request without freezing the UI, then waits for completion.
    import requests
    res: requests.Response = await atk.run_in_thread(
        root, lambda: requests.get("https://httpbin.org/delay/2"))


if __name__ == "__main__":
    main()

Differences from asynctkinter

asynctkinter:

  • Uses its own main loop instead of tkinter's built-in mainloop()
  • Uses its own timer mechanism instead of tkinter's built-in after()

asynctkinter2, on the other hand, relies entirely on tkinter's built-in components. This makes it much easier to coexist with other async libraries such as asyncio or trio.

Coexisting with asyncio

Coexistence does come with one important limitation: you cannot mix asyncio async operations and asynctkinter2 async operations inside the same async function:

async def this_does_not_work():
    await asyncio.sleep(1)
    await asynctkinter2.sleep(widget, 1000)

"Async operation" here means only code that uses the Python keywords async or await. The following is fine because, although it uses both asyncio and asynctkinter2, the asynctkinter2 side does not involve async/await:

async def this_works():
    await asyncio.sleep(1)
    task = asynctkinter2.start(...)

asyncio.create_task(this_works())

The next example is also fine because the asyncio side does not involve async/await:

async def this_also_works():
    task = asyncio.create_task(...)
    await asynctkinter2.sleep(widget, 1000)

asynctkinter2.start(this_also_works())

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asynctkinter2-0.1.2.tar.gz (4.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asynctkinter2-0.1.2-py3-none-any.whl (5.0 kB view details)

Uploaded Python 3

File details

Details for the file asynctkinter2-0.1.2.tar.gz.

File metadata

  • Download URL: asynctkinter2-0.1.2.tar.gz
  • Upload date:
  • Size: 4.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for asynctkinter2-0.1.2.tar.gz
Algorithm Hash digest
SHA256 691d79cfdcbccc2e6edd3a092ebb17efcccdab70e4bd7cd3e08022c089138af7
MD5 9f266ab6d32e46a9cb644bb1577f3b4c
BLAKE2b-256 95490ad71f835b7fbcc80e8e735f15b2916e8544f8e46c38252f691ef65e3536

See more details on using hashes here.

Provenance

The following attestation bundles were made for asynctkinter2-0.1.2.tar.gz:

Publisher: release.yml on asyncgui/asynctkinter2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file asynctkinter2-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: asynctkinter2-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 5.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for asynctkinter2-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b4e33e82a25a282a981a145f49f992e8627f91ad108f86520172ad71dd37143e
MD5 2d0d8a2aaf2f16b6ba9c878311432d2b
BLAKE2b-256 5175d172747b4492aaafd07f6339bf59c6a737f3e6a1bdc4408667956323fe5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for asynctkinter2-0.1.2-py3-none-any.whl:

Publisher: release.yml on asyncgui/asynctkinter2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page