async-tkinter-loop icon indicating copy to clipboard operation
async-tkinter-loop copied to clipboard

Dialogs (such as messagebox) block async mainloop

Open insolor opened this issue 1 year ago • 5 comments

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)

insolor avatar Apr 27 '23 10:04 insolor

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

  1. register async task 5ms later to stop async loop
  2. we run loop "forewer"
  3. when we unblock 5ms later, we register same tkinter callback 1ms later

Proof of concept: https://gist.github.com/ra1u/8aa66c09e985dd2a9fe297bcd222ddf7

ra1u avatar Feb 18 '24 20:02 ra1u

@ra1u interesting, I'll take a look later

insolor avatar Feb 27 '24 05:02 insolor

@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 avatar Aug 23 '24 02:08 ghmanoj

@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).

insolor avatar Aug 23 '24 05:08 insolor

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.

ra1u avatar Aug 23 '24 08:08 ra1u