From 1d5124fb78db7f073780fd4859db2d548d0d0f79 Mon Sep 17 00:00:00 2001 From: KomalDeep355 Date: Fri, 19 Jun 2026 13:34:52 +0530 Subject: [PATCH 1/5] ENH: Add paused kwarg to Animation and is_running() to TimerBase --- lib/matplotlib/animation.py | 7 ++++--- lib/matplotlib/backend_bases.py | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 7146dc28fcc9..153867acc0a3 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -883,9 +883,9 @@ class Animation: FuncAnimation, ArtistAnimation """ - def __init__(self, fig, event_source, blit=False): + def __init__(self, fig, event_source, blit=False, *, paused=False): self._draw_was_started = False - + self._paused_at_start = paused self._fig = fig # Disables blitting for backends that don't support it. This # allows users to request it if available, but still have a @@ -934,7 +934,8 @@ def _start(self, *args): # Now do any initial draw self._init_draw() # Actually start the event_source. - self.event_source.start() + if not self._paused_at_start: + self.event_source.start() def _stop(self, *args): # On stop we disconnect all of our events. diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 27c3752858a7..99e472e41d86 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1072,6 +1072,7 @@ def __init__(self, interval=None, callbacks=None): # Set .interval and not ._interval to go through the property setter. self.interval = 1000 if interval is None else interval self.single_shot = False + self._running = False def __del__(self): """Need to stop timer and possibly disconnect timer.""" @@ -1080,10 +1081,16 @@ def __del__(self): def start(self): """Start the timer.""" self._timer_start() + self._running = True def stop(self): """Stop the timer.""" self._timer_stop() + self._running = False + + def is_running(self): + """Return whether the timer is currently running.""" + return self._running def _timer_start(self): pass From 0e4bd1e35dc0bba9a38e67001699edd7e674fd68 Mon Sep 17 00:00:00 2001 From: KomalDeep355 Date: Fri, 19 Jun 2026 14:13:49 +0530 Subject: [PATCH 2/5] TEST: Add tests for Animation paused kwarg and TimerBase.is_running --- lib/matplotlib/tests/test_animation.py | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index a00adcdf95f0..676ef813401f 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -558,3 +558,32 @@ def test_animation_with_transparency(): # Check that the alpha channel is not 255, so frame has transparency assert frame.getextrema()[3][0] < 255 plt.close(fig) + +def test_animation_paused_start(): + """Test that paused=True prevents the animation from auto-starting.""" + fig, ax = plt.subplots() + line, = ax.plot([], []) + + def update(frame): + return line, + + ani = animation.FuncAnimation(fig, update, frames=5, paused=True) + fig.canvas.draw() # triggers the first draw_event / _start callback + + assert not ani.event_source.is_running() + plt.close(fig) + + +def test_animation_default_starts(): + """Test that the default paused=False still auto-starts.""" + fig, ax = plt.subplots() + line, = ax.plot([], []) + + def update(frame): + return line, + + ani = animation.FuncAnimation(fig, update, frames=5) + fig.canvas.draw() + + assert ani.event_source.is_running() + plt.close(fig) \ No newline at end of file From ac308950b4168bb0a9413a65641ac42bfc779103 Mon Sep 17 00:00:00 2001 From: KomalDeep355 Date: Fri, 19 Jun 2026 14:20:25 +0530 Subject: [PATCH 3/5] DOC: Add release note for paused Animation kwarg --- doc/release/next_whats_new/animation_paused_start.rst | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/release/next_whats_new/animation_paused_start.rst diff --git a/doc/release/next_whats_new/animation_paused_start.rst b/doc/release/next_whats_new/animation_paused_start.rst new file mode 100644 index 000000000000..f7f3a3594d4c --- /dev/null +++ b/doc/release/next_whats_new/animation_paused_start.rst @@ -0,0 +1,9 @@ +Animations can now be created in a paused state +-------------------------------------------------------------------------------- +'.Animation' now accepts a 'paused' keyword argument. When set to 'True', the animation will not automatically start when the figure is first drawn. +This allows starting an animation in a paused state without needing to access private API. Additionally, '.TimerBase.is_running' was added to query whether the underlying event source is currently running. +:: + ani = FuncAnimation(fig, update, frames=10, paused=True) + ani.event_source.is_running() # False + ani.resume() + ani.event_source.is_running() # True \ No newline at end of file From 17848404182dcf8030c1b3828aa4204071762ba6 Mon Sep 17 00:00:00 2001 From: KomalDeep355 Date: Fri, 19 Jun 2026 15:18:14 +0530 Subject: [PATCH 4/5] FIX: Add paused kwarg and is_running to type stubs, fix lint issues --- lib/matplotlib/animation.pyi | 7 ++++++- lib/matplotlib/backend_bases.pyi | 1 + lib/matplotlib/tests/test_animation.py | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/animation.pyi b/lib/matplotlib/animation.pyi index e90a0103aefd..52da52b9a92c 100644 --- a/lib/matplotlib/animation.pyi +++ b/lib/matplotlib/animation.pyi @@ -162,7 +162,12 @@ class Animation: frame_seq: Iterable[Artist] event_source: EventSourceProtocol | None # TODO: We should remove None def __init__( - self, fig: Figure, event_source: EventSourceProtocol, blit: bool = ... + self, + fig: Figure, + event_source: EventSourceProtocol, + blit: bool = ..., + *, + paused: bool = ..., ) -> None: ... def __del__(self) -> None: ... def save( diff --git a/lib/matplotlib/backend_bases.pyi b/lib/matplotlib/backend_bases.pyi index 94a8522717cd..f63bf517cf99 100644 --- a/lib/matplotlib/backend_bases.pyi +++ b/lib/matplotlib/backend_bases.pyi @@ -200,6 +200,7 @@ class TimerBase: def __del__(self) -> None: ... def start(self) -> None: ... def stop(self) -> None: ... + def is_running(self) -> bool: ... @property def interval(self) -> int: ... @interval.setter diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index 676ef813401f..3bc3c34e13ac 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -559,6 +559,7 @@ def test_animation_with_transparency(): assert frame.getextrema()[3][0] < 255 plt.close(fig) + def test_animation_paused_start(): """Test that paused=True prevents the animation from auto-starting.""" fig, ax = plt.subplots() @@ -586,4 +587,4 @@ def update(frame): fig.canvas.draw() assert ani.event_source.is_running() - plt.close(fig) \ No newline at end of file + plt.close(fig) From 1b426a1e2be89b0c9c7c7cebcdaeda76dd10c2aa Mon Sep 17 00:00:00 2001 From: KomalDeep355 Date: Fri, 19 Jun 2026 15:57:56 +0530 Subject: [PATCH 5/5] DOC: Fix RST formatting and line endings in release note --- .../next_whats_new/animation_paused_start.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/release/next_whats_new/animation_paused_start.rst b/doc/release/next_whats_new/animation_paused_start.rst index f7f3a3594d4c..6d8a3303e969 100644 --- a/doc/release/next_whats_new/animation_paused_start.rst +++ b/doc/release/next_whats_new/animation_paused_start.rst @@ -1,9 +1,14 @@ Animations can now be created in a paused state --------------------------------------------------------------------------------- -'.Animation' now accepts a 'paused' keyword argument. When set to 'True', the animation will not automatically start when the figure is first drawn. -This allows starting an animation in a paused state without needing to access private API. Additionally, '.TimerBase.is_running' was added to query whether the underlying event source is currently running. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +'.Animation' now accepts a 'paused' keyword argument. When set to 'True', +the animation will not automatically start when the figure is first drawn. +This allows starting an animation in a paused state without needing to +access private API. Additionally, '.TimerBase.is_running' was added to +query whether the underlying event source is currently running. + :: + ani = FuncAnimation(fig, update, frames=10, paused=True) ani.event_source.is_running() # False ani.resume() - ani.event_source.is_running() # True \ No newline at end of file + ani.event_source.is_running() # True