On 1/5/2023 4:24 PM, Stefan Ram wrote:
You often can replace threads in tkinter by coroutines usingCool! Can we have a link, please?
asyncio when you write a replacement for the mainloop of
tkinter that uses asyncio. Now, try to read only the official
documentation of asyncio and tkinter and figure out only from
this how to get such a program to work!
Thomas Passin <list1@tompassin.net> writes:
On 1/5/2023 4:24 PM, Stefan Ram wrote:
You often can replace threads in tkinter by coroutines usingCool! Can we have a link, please?
asyncio when you write a replacement for the mainloop of
tkinter that uses asyncio. Now, try to read only the official
documentation of asyncio and tkinter and figure out only from
this how to get such a program to work!
I do not post links, but tried to create a minimal example app.
import asyncio
import logging
import tkinter
# This program was tested on Windows, it is experimental.
# It should open a tkinter root window.
# Ctrl-E should create a task. You should be able to create
# a new task even while one task is already running.
# Each task will end after about 10 seconds.
# Ctrl-X should exit the process.
# Or, use the menu "Action".
# I (Stefan Ram) designed and wrote the program, but especially
# the code in "app_async_mainloop" and "terminate_tasks" was
# written following educational material from the World-Wide Web.
class app_class( tkinter.Tk ):
def __init__( self, *args, **kwargs ):
self.is_running = 1_000_000
super().__init__( *args, **kwargs )
root = self
root.protocol( "WM_DELETE_WINDOW", self.app_exit_macro )
async def app_example_task( self, example_label ):
try:
for i in range( 10 ):
example_label[ 'text' ]=str( i )
await asyncio.sleep( 1 )
except asyncio.CancelledError:
pass
example_label.destroy()
def app_example_macro( self ):
root = self
example_label=tkinter.Label( root )
example_label.pack()
asyncio.get_running_loop().create_task\
( self.app_example_task( example_label ))
root = self
def terminate_tasks( self ):
loop = asyncio.get_running_loop()
pending = asyncio.all_tasks( loop=loop )
label_tasks = []
for task in pending:
if 'app_example_task' in str( task ):
label_tasks.append( task )
task.cancel()
group = asyncio.gather( *label_tasks, return_exceptions=True )
try:
loop.run_until_complete( group )
except AssertionError:
# ignoring an assertion error on Windows I do not understand
pass
def app_exit_macro( self ):
self.terminate_tasks()
self.is_running = 99
root = self
root.destroy()
def app_add_basemenu( self, example=False ):
root = self
menubar = tkinter.Menu( root )
menu = tkinter.Menu( menubar, tearoff=0 )
name = "Actions"; menu = tkinter.Menu( menubar, tearoff=0 )
if example:
text = "Example";
callback = self.app_example_macro; menu.add_command\
( label=text, underline=0, command=callback,
accelerator="Control-e" );
root.bind\
( "<Control-e>", lambda event, callback=callback:callback() )
text = "Exit";
callback = self.app_exit_macro
menu.add_command\
( label=text, underline=1,
command=callback, accelerator="Control-x" )
root.bind\
( "<Control-x>", lambda event,callback=callback: callback() )
menubar.add_cascade( label=name, underline=0, menu=menu )
root.config( menu=menubar )
async def app_async_mainloop( self ):
root = self
root.willdispatch()
root.tk.dooneevent( tkinter._tkinter.DONT_WAIT )
while self.is_running > 0:
if self.is_running < 1_000_000: self.is_running -= 1
try:
await asyncio.sleep\
( tkinter._tkinter.getbusywaitinterval() / 10_000 )
root.tk.dooneevent( tkinter._tkinter.DONT_WAIT )
root.update()
except tkinter.TclError:
break
async def app_async_main( self ):
try:
await self.app_async_mainloop()
except asyncio.CancelledError:
logging.debug( f'asyncio.CancelledError' )
def app_async_run( self ):
asyncio.run( self.app_async_main() )
app = app_class()
app.app_add_basemenu(example=True)
app.app_async_run()
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 307 |
Nodes: | 16 (2 / 14) |
Uptime: | 54:46:57 |
Calls: | 6,914 |
Calls today: | 4 |
Files: | 12,379 |
Messages: | 5,430,460 |