Created
August 26, 2021 19:14
-
-
Save aleroddepaz/455d9c0c618bff7ce9aed18ab7160c22 to your computer and use it in GitHub Desktop.
Tkinter and asyncio proof of concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import tkinter as tk | |
# Concepts | |
# https://www.tcl.tk/man/tcl8.7/TkLib/MainLoop.html | |
# https://www.tcl.tk/man/tcl8.7/TclLib/DoOneEvent.html | |
# https://www.tcl.tk/man/tcl8.7/TclCmd/update.html | |
# https://www.tcl.tk/man/tcl8.7/TclCmd/after.html | |
# SO related questions | |
# https://stackoverflow.com/q/56453327/why-does-tkinter-tk-update-block-while-the-window-is-being-resized | |
# https://stackoverflow.com/q/28934079/substitute-for-tkinter-dooneevent | |
# https://stackoverflow.com/q/49958180/using-async-await-keywords-with-tk-after-method-of-tkinter | |
# https://stackoverflow.com/q/66656533/tcl-dooneevent-is-blocked-if-tkwait-vwait-is-called | |
class App(tk.Tk): | |
def __init__(self): | |
super().__init__() | |
callback = lambda: asyncio.create_task(self.submit()) | |
self.btn = tk.Button(self, text='Go!', command=callback) | |
self.btn.pack(padx=100, pady=20) | |
async def submit(self): | |
self.btn.config(state=tk.DISABLED) | |
await asyncio.sleep(3) | |
self.btn.config(state=tk.NORMAL) | |
# https://www.reddit.com/r/Python/comments/33ecpl/ | |
async def main(): | |
# Replicate sleep interval from CPython | |
# https://github.com/python/cpython/blob/main/Modules/_tkinter.c#L2947 | |
interval = tk._tkinter.getbusywaitinterval() / 1000 | |
# Get the global Tk instance while it is not destroyed | |
# https://github.com/python/cpython/blob/main/Lib/tkinter/__init__.py#L2344 | |
while tk._default_root: | |
# Enter the event loop (it blocks until all all events are processed!) | |
# https://github.com/python/cpython/blob/main/Modules/_tkinter.c#L2943 | |
tk._default_root.dooneevent(tk._tkinter.DONT_WAIT) | |
await asyncio.sleep(interval) | |
if __name__ == '__main__': | |
#https://bugs.python.org/issue27546 | |
app = App() | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment