Skip to content

Repository files navigation

Asynchronous Tkinter Mainloop

Python testsDocumentationCoverage StatusMaintainability
PyPISupported Python versions

Implementation of asynchronous mainloop for tkinter, the use of which allows using async handler functions. It is intended to be as simple to use as possible. No fancy unusual syntax or constructions - just use an alternative function instead of root.mainloop() and wrap asynchronous handlers into a helper function.

Note
Please, fill free to report bugs, add pull requests or share your thoughts / ask questions, etc. about the module.

Based on ideas from:

Installation

Install the package with the following command:

pip install async-tkinter-loop

or

pip install "async-tkinter-loop[examples]"
  • [examples] part is needed to install optional dependencies (such as httpx and pillow) to run some of the examples. If you're not going to run examples, remove the [examples] part from the command
  • Use pip3 instead of pip on Linux systems to install the package for python3 (not python2)
  • Probably you'll want to create a virtual environment for experiments with this library, but this is optional.
  • If you want to try examples, download the entire repository as an archive (green "code" button on the GitHub page → "Download ZIP"), unpack, run any example (of course, you need to install optional dependencies)

Some examples

Basic example:

importasyncioimporttkinterastkfromasync_tkinter_loopimportasync_handler, async_mainloopasyncdefcounter():
i=0whileTrue:
i+=1label.config(text=str(i))
awaitasyncio.sleep(1.0)
root=tk.Tk()
label=tk.Label(root)
label.pack()
tk.Button(root, text="Start", command=async_handler(counter)).pack()
async_mainloop(root)

Also, async_handler function can be used as a decorator (but it makes a decorated function syncroneous):

importasyncioimporttkinterastkfromasync_tkinter_loopimportasync_handler, async_mainloop@async_handlerasyncdefcounter():
i=0whileTrue:
i+=1label.config(text=str(i))
awaitasyncio.sleep(1.0)
root=tk.Tk()
label=tk.Label(root)
label.pack()
tk.Button(root, text="Start", command=counter).pack()
async_mainloop(root)

A more practical example, downloading an image from the Internet with httpx (you can use aiohttp as well) and displaying it in the Tkinter window:

importtkinterastkfromioimportBytesIOimporthttpxfromPILimportImage, ImageTkfromasync_tkinter_loopimportasync_handler, async_mainloopasyncdefload_image(url):
button.config(state=tk.DISABLED)
label.config(text="Loading...", image="")
asyncwithhttpx.AsyncClient() asclient:
response=awaitclient.get(url, follow_redirects=True)
ifresponse.status_code!=200:
label.config(text=f"HTTP error {response.status_code}")
else:
content=response.contentpil_image=Image.open(BytesIO(content))
image=ImageTk.PhotoImage(pil_image)
label.image=imagelabel.config(image=image, text="")
button.config(state=tk.NORMAL)
url="https://picsum.photos/800/640"root=tk.Tk()
root.geometry("800x640")
button=tk.Button(root, text="Load an image", command=async_handler(load_image, url))
button.pack()
label=tk.Label(root)
label.pack(expand=1, fill=tk.BOTH)
async_mainloop(root)

More examples see in the examples directory.

About

Asynchronous mainloop implementation for tkinter. Makes it possible to use async functions as event handlers and widget commands.

Topics

Resources

Stars

94 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages