Skip to content

Instantly share code, notes, and snippets.

@ra1u
Last active January 16, 2024 14:58
Show Gist options
  • Save ra1u/8aa66c09e985dd2a9fe297bcd222ddf7 to your computer and use it in GitHub Desktop.
Save ra1u/8aa66c09e985dd2a9fe297bcd222ddf7 to your computer and use it in GitHub Desktop.
import asyncio
import logging
import tkinter as tk
from tkinter import messagebox
from async_tkinter_loop import async_handler, get_event_loop
root = tk.Tk()
class AsyncTk():
def __init__(self,root):
self.root = root
self.recurse_cnt = 0
def _run_async_cb(self):
# blocking call to loop
self.recurse_cnt += 1
if self.recurse_cnt > 1:
print("Warning: recursion detected")
self.loop.create_task(self._stop_loop_later())
# run loop blocking mode untill stop in _stop_loop_later is called
self.loop.run_forever()
#self._register_async_cb_now()
self._register_async_cb_later()
self.recurse_cnt -= 1
def _register_async_cb_later(self):
self.root.after(1,self._run_async_cb)
def _register_async_cb_now(self):
self.root.after_idle(self._run_async_cb)
async def _stop_loop_later(self):
await asyncio.sleep(0.005)
self.loop.stop()
def start(self):
self._register_async_cb_later()
@property
def loop(self):
return get_event_loop()
async def async_dispatch(root,cb):
# call sync_call (cb) "async" (cb must be one of blocking calls from tkinter - MessageBox, FileDialog, etc.)
queue = asyncio.Queue(maxsize=1)
def sync_call():
r = cb()
async def push_result():
await queue.put(r)
get_event_loop().create_task(push_result())
root.after_idle(sync_call)
q = await queue.get()
return q
@async_handler
async def loop():
while True:
counter.set(counter.get() + 1)
await asyncio.sleep(0.01)
@async_handler
async def show_message():
# messagebox is "blocking" so we need to call as blocking (no async function / cb)
#
# or use async_dispatch
r = await async_dispatch(root,lambda: messagebox.showinfo("Info", "Some info"))
logging.debug(f"messagebox result: {r}")
logging.basicConfig(level=logging.DEBUG)
counter = tk.IntVar()
tk.Label(root, textvariable=counter).pack()
tk.Button(root, text="Start counter", command=loop).pack()
tk.Button(root, text="Show message", command=show_message).pack()
as_tk = AsyncTk(root)
as_tk.start()
#async_mainloop(root)
root.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment