From 73d1af2eef105caae45fdc8577bfef0d1bc53126 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 3 Jun 2022 01:37:03 +0200 Subject: [PATCH] Move draw_if_interactive logic to new_figure_manager_given_figure. Currently, Matplotlib only ever calls draw_if_interactive at the end of `plt.figure()` (and upon figure unpickling), i.e. this is a mechanism to further customize handling of newly generated figures. (Prior to Matplotlib 1.5, draw_if_interactive was also called at the end of all pyplot functions to trigger a figure redraw, but this is now handled by the stale attribute.) In order to simplify the backend API ("what is the API that a backend module must/can provide", I am planning to deprecate (on Matplotlib's side) the ability for backends to provide a draw_if_interactive function (forcing them to always do `if interactive(): draw_idle()`). Instead, any relevant new-figure-customization logic can instead go into `new_figure_manager_given_figure`. This PR implements this change for ipympl, and should be fully back-compatible all the way back to Matplotlib 1.5. I would like to make these changes first on the side of the clients (i.e., the third-party backends), to catch any possible problems with the intended change on Matplotlib's side. --- ipympl/backend_nbagg.py | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/ipympl/backend_nbagg.py b/ipympl/backend_nbagg.py index 1e99da45..cd098190 100644 --- a/ipympl/backend_nbagg.py +++ b/ipympl/backend_nbagg.py @@ -495,6 +495,21 @@ def destroy(event): Gcf.destroy(manager) cid = canvas.mpl_connect('close_event', destroy) + + # Only register figure for showing when in interactive mode (otherwise + # we'll generate duplicate plots, since a user who set ioff() manually + # expects to make separate draw/show calls). + if is_interactive(): + # ensure current figure will be drawn. + try: + _Backend_ipympl._to_show.remove(figure) + except ValueError: + # ensure it only appears in the draw list once + pass + # Queue up the figure for drawing in next show() call + _Backend_ipympl._to_show.append(figure) + _Backend_ipympl._draw_called = True + return manager @staticmethod @@ -523,32 +538,6 @@ def show(block=None): if manager.canvas.figure in _Backend_ipympl._to_show: _Backend_ipympl._to_show.remove(manager.canvas.figure) - @staticmethod - def draw_if_interactive(): - # If matplotlib was manually set to non-interactive mode, this function - # should be a no-op (otherwise we'll generate duplicate plots, since a - # user who set ioff() manually expects to make separate draw/show - # calls). - if not is_interactive(): - return - - manager = Gcf.get_active() - if manager is None: - return - fig = manager.canvas.figure - - # ensure current figure will be drawn, and each subsequent call - # of draw_if_interactive() moves the active figure to ensure it is - # drawn last - try: - _Backend_ipympl._to_show.remove(fig) - except ValueError: - # ensure it only appears in the draw list once - pass - # Queue up the figure for drawing in next show() call - _Backend_ipympl._to_show.append(fig) - _Backend_ipympl._draw_called = True - def flush_figures(): if rcParams['backend'] == 'module://ipympl.backend_nbagg':