From 894f3cf3e5363a175fe94afb647d87a10aa1f76f Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 23 Jan 2020 01:18:45 +0100 Subject: [PATCH] Don't recursively call draw_idle when updating artists at draw time. --- lib/matplotlib/backend_bases.py | 6 ++++-- lib/matplotlib/backends/backend_qt5.py | 21 +++++++++++---------- lib/matplotlib/pyplot.py | 11 +++++++++-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 3352579ff061..215c6ae9c5c9 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1617,8 +1617,10 @@ def _fix_ipython_backend2gui(cls): @contextmanager def _idle_draw_cntx(self): self._is_idle_drawing = True - yield - self._is_idle_drawing = False + try: + yield + finally: + self._is_idle_drawing = False def is_saving(self): """ diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index f59440eff7e0..5f96eeff51af 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -481,16 +481,17 @@ def draw_idle(self): QtCore.QTimer.singleShot(0, self._draw_idle) def _draw_idle(self): - if not self._draw_pending: - return - self._draw_pending = False - if self.height() < 0 or self.width() < 0: - return - try: - self.draw() - except Exception: - # Uncaught exceptions are fatal for PyQt5, so catch them instead. - traceback.print_exc() + with self._idle_draw_cntx(): + if not self._draw_pending: + return + self._draw_pending = False + if self.height() < 0 or self.width() < 0: + return + try: + self.draw() + except Exception: + # Uncaught exceptions are fatal for PyQt5, so catch them. + traceback.print_exc() def drawRectangle(self, rect): # Draw the zoom rectangle to the QPainter. _draw_rect_callback needs diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 1d1e294e6a0a..0bacf6cd0919 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -565,8 +565,15 @@ def _auto_draw_if_interactive(fig, val): fig : Figure A figure object which is assumed to be associated with a canvas """ - if val and matplotlib.is_interactive() and not fig.canvas.is_saving(): - fig.canvas.draw_idle() + if (val and matplotlib.is_interactive() + and not fig.canvas.is_saving() + and not fig.canvas._is_idle_drawing): + # Some artists can mark themselves as stale in the middle of drawing + # (e.g. axes position & tick labels being computed at draw time), but + # this shouldn't trigger a redraw because the current redraw will + # already take them into account. + with fig.canvas._idle_draw_cntx(): + fig.canvas.draw_idle() def gcf():