@@ -166,6 +166,7 @@ def __init__(self, figure=None, master=None, resize_callback=None):
166166 super ().__init__ (figure )
167167 self ._idle = True
168168 self ._idle_callback = None
169+ self ._event_loop_id = None
169170 w , h = self .figure .bbox .size .astype (int )
170171 self ._tkcanvas = tk .Canvas (
171172 master = master , background = "white" ,
@@ -374,11 +375,20 @@ def flush_events(self):
374375 def start_event_loop (self , timeout = 0 ):
375376 # docstring inherited
376377 if timeout > 0 :
377- self ._master .after (int (1000 * timeout ), self .stop_event_loop )
378+ milliseconds = int (1000 * timeout )
379+ if milliseconds > 0 :
380+ self ._event_loop_id = self ._tkcanvas .after (
381+ milliseconds , self .stop_event_loop )
382+ else :
383+ self ._event_loop_id = self ._tkcanvas .after_idle (
384+ self .stop_event_loop )
378385 self ._master .mainloop ()
379386
380387 def stop_event_loop (self ):
381388 # docstring inherited
389+ if self ._event_loop_id :
390+ self ._master .after_cancel (self ._event_loop_id )
391+ self ._event_loop_id = None
382392 self ._master .quit ()
383393
384394
@@ -454,6 +464,8 @@ def destroy(*args):
454464 def destroy (self , * args ):
455465 if self .canvas ._idle_callback :
456466 self .canvas ._tkcanvas .after_cancel (self .canvas ._idle_callback )
467+ if self .canvas ._event_loop_id :
468+ self .canvas ._tkcanvas .after_cancel (self .canvas ._event_loop_id )
457469
458470 # NOTE: events need to be flushed before issuing destroy (GH #9956),
459471 # however, self.window.update() can break user code. This is the
@@ -466,7 +478,8 @@ def delayed_destroy():
466478 if self ._owns_mainloop and not Gcf .get_num_fig_managers ():
467479 self .window .quit ()
468480
469- self .window .after_idle (delayed_destroy )
481+ # "after idle after 0" avoids Tcl error/race (GH #19940)
482+ self .window .after_idle (self .window .after , 0 , delayed_destroy )
470483
471484 def get_window_title (self ):
472485 return self .window .wm_title ()
0 commit comments