async-tkinter-loop
async-tkinter-loop copied to clipboard
Dialogs (such as messagebox) block async mainloop
In the following code (pure tkinter) counter continues to work while messagebox dialog is shown:
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
def loop():
counter.set(counter.get() + 1)
root.after(1000, loop)
def show_message():
messagebox.showinfo("Info", "Some info")
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()
root.mainloop()
But with the corresponding code with async_tkinter_loop
counter is paused when messagebox is shown:
import asyncio
import tkinter as tk
from tkinter import messagebox
from async_tkinter_loop import async_mainloop, async_handler
root = tk.Tk()
@async_handler
async def loop():
while True:
counter.set(counter.get() + 1)
await asyncio.sleep(1.0)
def show_message():
messagebox.showinfo("Info", "Some info")
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()
async_mainloop(root)
Thank you for this libraray: I got same issue.
My solution was to turn things around. Instead of running tkinter on top of async, it runs async loop inside tkinter.
We start tkinter and register callback 1ms later. In callback from tkinter we do blocking call
- register async task 5ms later to stop async loop
- we run loop "forewer"
- when we unblock 5ms later, we register same tkinter callback 1ms later
Proof of concept: https://gist.github.com/ra1u/8aa66c09e985dd2a9fe297bcd222ddf7
@ra1u interesting, I'll take a look later
@insolor Any updates on this? Most probably the issue I am facing is also related to this. When I let a long running async function start and then drag the tkinter window the async function pauses and continues again only after I leave the window from dragging.
@ghmanoj this is probably a similar problem, but not the same one. In your case, if you need a non-stopping async function try to run the function in a separate thread, it should help (it won't help with dialogs though).
If i recall correctly there is "bug" in MS Windows tkinter, that when you drag window around holding top menu bar, there is 100% cpu utilisation, because Windows is sending lot notifications on tkinter. Workaround is, that you replace default top bar, with tkinter widget including custom bar and custom X button on right. I am not sure that what is presented in current issue will help with this 100% cpu issue.