# Asynchronous Tkinter Mainloop
[![Python tests](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml/badge.svg)](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml)
[![Documentation](https://github.com/insolor/async-tkinter-loop/actions/workflows/deploy-docs.yml/badge.svg)](https://insolor.github.io/async-tkinter-loop/)
[![Coverage Status](https://coveralls.io/repos/github/insolor/async-tkinter-loop/badge.svg?branch=main)](https://coveralls.io/github/insolor/async-tkinter-loop?branch=main)
[![Maintainability](https://api.codeclimate.com/v1/badges/2566146b14ef72177613/maintainability)](https://codeclimate.com/github/insolor/async-tkinter-loop/maintainability)
[![PyPI](https://img.shields.io/pypi/v/async-tkinter-loop)](https://pypi.org/project/async-tkinter-loop/)
![Supported Python versions](https://img.shields.io/pypi/pyversions/async-tkinter-loop)
<!--![PyPI - Downloads](https://img.shields.io/pypi/dm/async-tkinter-loop)-->
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](https://github.com/insolor/async-tkinter-loop/issues), add [pull requests](https://github.com/insolor/async-tkinter-loop/pulls) or [share your thoughts / ask questions, etc.](https://github.com/insolor/async-tkinter-loop/discussions) about the module.
Based on ideas from:
* my answer on ru.stackoverflow.com: <https://ru.stackoverflow.com/a/1043146>
* answer of [Terry Jan Reedy](https://stackoverflow.com/users/722804) on stackoverflow.com:
<https://stackoverflow.com/a/47896365>
* answer of [jfs](https://ru.stackoverflow.com/users/23044) on ru.stackoverflow.com:
<https://ru.stackoverflow.com/a/804609>
## 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](https://github.com/insolor/async-tkinter-loop) →
"Download ZIP"), unpack, run any example (of course, you need to install optional dependencies)
## Some examples
Basic example:
```python
import asyncio
import tkinter as tk
from async_tkinter_loop import async_handler, async_mainloop
async def counter():
i = 0
while True:
i += 1
label.config(text=str(i))
await asyncio.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):
```python
import asyncio
import tkinter as tk
from async_tkinter_loop import async_handler, async_mainloop
@async_handler
async def counter():
i = 0
while True:
i += 1
label.config(text=str(i))
await asyncio.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](https://github.com/encode/httpx)
(you can use [aiohttp](https://github.com/aio-libs/aiohttp) as well)
and displaying it in the Tkinter window:
```python
import tkinter as tk
from io import BytesIO
import httpx
from PIL import Image, ImageTk
from async_tkinter_loop import async_handler, async_mainloop
async def load_image(url):
button.config(state=tk.DISABLED)
label.config(text="Loading...", image="")
async with httpx.AsyncClient() as client:
response = await client.get(url, follow_redirects=True)
if response.status_code != 200:
label.config(text=f"HTTP error {response.status_code}")
else:
content = response.content
pil_image = Image.open(BytesIO(content))
image = ImageTk.PhotoImage(pil_image)
label.image = image
label.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`](https://github.com/insolor/async-tkinter-loop/tree/main/examples) directory.
Raw data
{
"_id": null,
"home_page": "https://github.com/insolor/async-tkinter-loop",
"name": "async-tkinter-loop",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "tkinter,async,async-await,asyncio,aiohttp",
"author": "insolor",
"author_email": "insolor@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/4a/cd/6d61fb996178deabf8b7cce8d815986c1cc5eb7bb8aaed7085eccc76906b/async_tkinter_loop-0.9.3.tar.gz",
"platform": null,
"description": "# Asynchronous Tkinter Mainloop\n\n[![Python tests](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml/badge.svg)](https://github.com/insolor/async-tkinter-loop/actions/workflows/python-tests.yml)\n[![Documentation](https://github.com/insolor/async-tkinter-loop/actions/workflows/deploy-docs.yml/badge.svg)](https://insolor.github.io/async-tkinter-loop/)\n[![Coverage Status](https://coveralls.io/repos/github/insolor/async-tkinter-loop/badge.svg?branch=main)](https://coveralls.io/github/insolor/async-tkinter-loop?branch=main)\n[![Maintainability](https://api.codeclimate.com/v1/badges/2566146b14ef72177613/maintainability)](https://codeclimate.com/github/insolor/async-tkinter-loop/maintainability)\n[![PyPI](https://img.shields.io/pypi/v/async-tkinter-loop)](https://pypi.org/project/async-tkinter-loop/)\n![Supported Python versions](https://img.shields.io/pypi/pyversions/async-tkinter-loop)\n<!--![PyPI - Downloads](https://img.shields.io/pypi/dm/async-tkinter-loop)-->\n\nImplementation of asynchronous `mainloop` for tkinter, the use of which allows using `async` handler functions.\nIt is intended to be as simple to use as possible. No fancy unusual syntax or constructions - just use an alternative\nfunction instead of `root.mainloop()` and wrap asynchronous handlers into a helper function.\n\n> **Note** \n> Please, fill free to [report bugs](https://github.com/insolor/async-tkinter-loop/issues), add [pull requests](https://github.com/insolor/async-tkinter-loop/pulls) or [share your thoughts / ask questions, etc.](https://github.com/insolor/async-tkinter-loop/discussions) about the module.\n\nBased on ideas from:\n\n* my answer on ru.stackoverflow.com: <https://ru.stackoverflow.com/a/1043146>\n* answer of [Terry Jan Reedy](https://stackoverflow.com/users/722804) on stackoverflow.com:\n <https://stackoverflow.com/a/47896365>\n* answer of [jfs](https://ru.stackoverflow.com/users/23044) on ru.stackoverflow.com:\n <https://ru.stackoverflow.com/a/804609>\n\n## Installation\n\nInstall the package with the following command:\n\n```\npip install async-tkinter-loop\n```\nor\n```\npip install async-tkinter-loop[examples]\n```\n\n- `[examples]` part is needed to install optional dependencies (such as `httpx` and `pillow`) to run some of the\n examples. If you're not going to run examples, remove the `[examples]` part from the command\n- Use `pip3` instead of `pip` on Linux systems to install the package for python3 (not python2)\n- Probably you'll want to create a virtual environment for experiments with this library, but this is optional.\n- If you want to try examples, download the entire repository as an archive (green \"code\" button on\n [the GitHub page](https://github.com/insolor/async-tkinter-loop) \u2192\n \"Download ZIP\"), unpack, run any example (of course, you need to install optional dependencies)\n\n## Some examples\n\nBasic example:\n```python\nimport asyncio\nimport tkinter as tk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\nasync def counter():\n i = 0\n while True:\n i += 1\n label.config(text=str(i))\n await asyncio.sleep(1.0)\n\n\nroot = tk.Tk()\n\nlabel = tk.Label(root)\nlabel.pack()\n\ntk.Button(root, text=\"Start\", command=async_handler(counter)).pack()\n\nasync_mainloop(root)\n```\n\nAlso, `async_handler` function can be used as a decorator (but it makes a decorated function syncroneous):\n\n```python\nimport asyncio\nimport tkinter as tk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\n@async_handler\nasync def counter():\n i = 0\n while True:\n i += 1\n label.config(text=str(i))\n await asyncio.sleep(1.0)\n\n\nroot = tk.Tk()\n\nlabel = tk.Label(root)\nlabel.pack()\n\ntk.Button(root, text=\"Start\", command=counter).pack()\n\nasync_mainloop(root)\n```\n\nA more practical example, downloading an image from the Internet with [httpx](https://github.com/encode/httpx)\n(you can use [aiohttp](https://github.com/aio-libs/aiohttp) as well)\nand displaying it in the Tkinter window:\n\n```python\nimport tkinter as tk\nfrom io import BytesIO\n\nimport httpx\nfrom PIL import Image, ImageTk\n\nfrom async_tkinter_loop import async_handler, async_mainloop\n\n\nasync def load_image(url):\n button.config(state=tk.DISABLED)\n label.config(text=\"Loading...\", image=\"\")\n\n async with httpx.AsyncClient() as client:\n response = await client.get(url, follow_redirects=True)\n if response.status_code != 200:\n label.config(text=f\"HTTP error {response.status_code}\")\n else:\n content = response.content\n pil_image = Image.open(BytesIO(content))\n image = ImageTk.PhotoImage(pil_image)\n label.image = image\n label.config(image=image, text=\"\")\n button.config(state=tk.NORMAL)\n\n\nurl = \"https://picsum.photos/800/640\"\n\nroot = tk.Tk()\nroot.geometry(\"800x640\")\n\nbutton = tk.Button(root, text=\"Load an image\", command=async_handler(load_image, url))\nbutton.pack()\n\nlabel = tk.Label(root)\nlabel.pack(expand=1, fill=tk.BOTH)\n\nasync_mainloop(root)\n```\n\nMore examples see in the [`examples`](https://github.com/insolor/async-tkinter-loop/tree/main/examples) directory.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Asynchronous mainloop implementation for tkinter",
"version": "0.9.3",
"project_urls": {
"Documentation": "https://insolor.github.io/async-tkinter-loop/",
"Homepage": "https://github.com/insolor/async-tkinter-loop",
"Repository": "https://github.com/insolor/async-tkinter-loop"
},
"split_keywords": [
"tkinter",
"async",
"async-await",
"asyncio",
"aiohttp"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8167c0cf42e835906979d6afbb8dc909ad11ada175340f09e950606b559c1a85",
"md5": "8bc3cae04c513166659331c3a3e7ba83",
"sha256": "4c69f46ffdbac48dc44c296c3a7b00c4cc4f852c3d43aa2fa329991d1fadea02"
},
"downloads": -1,
"filename": "async_tkinter_loop-0.9.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8bc3cae04c513166659331c3a3e7ba83",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 5915,
"upload_time": "2023-11-24T14:41:58",
"upload_time_iso_8601": "2023-11-24T14:41:58.576990Z",
"url": "https://files.pythonhosted.org/packages/81/67/c0cf42e835906979d6afbb8dc909ad11ada175340f09e950606b559c1a85/async_tkinter_loop-0.9.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4acd6d61fb996178deabf8b7cce8d815986c1cc5eb7bb8aaed7085eccc76906b",
"md5": "bbac9beadf4f729e6112a91e4298b2bd",
"sha256": "509c418139847bcb2e47a5a6b6d24a2e2dca290bc468dad6b6b8029e8a865bfd"
},
"downloads": -1,
"filename": "async_tkinter_loop-0.9.3.tar.gz",
"has_sig": false,
"md5_digest": "bbac9beadf4f729e6112a91e4298b2bd",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 5069,
"upload_time": "2023-11-24T14:42:00",
"upload_time_iso_8601": "2023-11-24T14:42:00.151102Z",
"url": "https://files.pythonhosted.org/packages/4a/cd/6d61fb996178deabf8b7cce8d815986c1cc5eb7bb8aaed7085eccc76906b/async_tkinter_loop-0.9.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-24 14:42:00",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "insolor",
"github_project": "async-tkinter-loop",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "async-tkinter-loop"
}