From e90e8ec6dcd3f600aa86890f056f3e1d74f05c26 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 27 Jan 2020 13:41:23 -0500 Subject: [PATCH] Backport PR #16298: 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 e2cc86ec5ef7..0c85673b2b10 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1652,8 +1652,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 e326a346e969..ee15bfbf369d 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 8c8ddbe947a2..1d28260ef328 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -586,8 +586,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():