On 1/5/2023 7:52 PM, Stefan Ram wrote:
Thomas Passin <li...@tompassin.net> writes:
On 1/5/2023 4:24 PM, Stefan Ram wrote:
You often can replace threads in tkinter by coroutines using
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!
Cool! Can we have a link, please?

   I do not post links, but tried to create a minimal example app.

Thanks! That's not exactly obvious, is it? Congratulations on getting it working.

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()




--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to