From 0870c5028aca3d9b52190f8c956876bfb68f3055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20W=C3=BCrtz?= Date: Wed, 8 Jul 2015 23:25:26 +0200 Subject: [PATCH 1/2] Deferred rendering for gui events in Qt5Agg (fixes #4604) --- lib/matplotlib/backends/backend_qt5.py | 17 +++-------------- lib/matplotlib/backends/backend_qt5agg.py | 3 ++- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index c39d406e0d28..6b4a49166362 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -334,8 +334,7 @@ def resizeEvent(self, event): hinch = h / dpival self.figure.set_size_inches(winch, hinch) FigureCanvasBase.resize_event(self) - self.draw() - self.update() + self.draw_idle() QtWidgets.QWidget.resizeEvent(self, event) def sizeHint(self): @@ -417,17 +416,7 @@ def stop_event_loop(self): stop_event_loop.__doc__ = FigureCanvasBase.stop_event_loop_default.__doc__ def draw_idle(self): - 'update drawing area only if idle' - d = self._idle - self._idle = False - - def idle_draw(*args): - try: - self.draw() - finally: - self._idle = True - if d: - QtCore.QTimer.singleShot(0, idle_draw) + self._priv_update() class MainWindow(QtWidgets.QMainWindow): @@ -666,7 +655,7 @@ def zoom(self, *args): self._update_buttons_checked() def dynamic_update(self): - self.canvas.draw() + self.canvas.draw_idle() def set_message(self, s): self.message.emit(s) diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index a97c1cf5ab86..38a7ce61d02c 100644 --- a/lib/matplotlib/backends/backend_qt5agg.py +++ b/lib/matplotlib/backends/backend_qt5agg.py @@ -63,7 +63,7 @@ class FigureCanvasQTAggBase(object): def drawRectangle(self, rect): self._drawRect = rect - self.repaint() + self.draw_idle() def paintEvent(self, e): """ @@ -71,6 +71,7 @@ def paintEvent(self, e): In Qt, all drawing should be done inside of here when a widget is shown onscreen. """ + FigureCanvasAgg.draw(self) # FigureCanvasQT.paintEvent(self, e) if DEBUG: From 7fb21c660a1ae17c27ef95b4790c2e71bf679b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20W=C3=BCrtz?= Date: Fri, 10 Jul 2015 06:31:45 +0200 Subject: [PATCH 2/2] Revert to using update() instead of redraw() for Qt5/Win --- lib/matplotlib/backends/backend_qt4agg.py | 16 ---------------- lib/matplotlib/backends/backend_qt5.py | 2 +- lib/matplotlib/backends/backend_qt5agg.py | 18 +----------------- 3 files changed, 2 insertions(+), 34 deletions(-) diff --git a/lib/matplotlib/backends/backend_qt4agg.py b/lib/matplotlib/backends/backend_qt4agg.py index 39b2793831e7..b6830573c983 100644 --- a/lib/matplotlib/backends/backend_qt4agg.py +++ b/lib/matplotlib/backends/backend_qt4agg.py @@ -73,22 +73,6 @@ def __init__(self, figure): self._drawRect = None self.blitbox = None self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent) - # it has been reported that Qt is semi-broken in a windows - # environment. If `self.draw()` uses `update` to trigger a - # system-level window repaint (as is explicitly advised in the - # Qt documentation) the figure responds very slowly to mouse - # input. The work around is to directly use `repaint` - # (against the advice of the Qt documentation). The - # difference between `update` and repaint is that `update` - # schedules a `repaint` for the next time the system is idle, - # where as `repaint` repaints the window immediately. The - # risk is if `self.draw` gets called with in another `repaint` - # method there will be an infinite recursion. Thus, we only - # expose windows users to this risk. - if sys.platform.startswith('win'): - self._priv_update = self.repaint - else: - self._priv_update = self.update FigureCanvas = FigureCanvasQTAgg diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 6b4a49166362..baf76593cc57 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -416,7 +416,7 @@ def stop_event_loop(self): stop_event_loop.__doc__ = FigureCanvasBase.stop_event_loop_default.__doc__ def draw_idle(self): - self._priv_update() + self.update() class MainWindow(QtWidgets.QMainWindow): diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index 38a7ce61d02c..2ab431bfccaa 100644 --- a/lib/matplotlib/backends/backend_qt5agg.py +++ b/lib/matplotlib/backends/backend_qt5agg.py @@ -147,7 +147,7 @@ def draw(self): # causes problems with code that uses the result of the # draw() to update plot elements. FigureCanvasAgg.draw(self) - self._priv_update() + self.update() def blit(self, bbox=None): """ @@ -184,22 +184,6 @@ def __init__(self, figure): self._drawRect = None self.blitbox = None self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent) - # it has been reported that Qt is semi-broken in a windows - # environment. If `self.draw()` uses `update` to trigger a - # system-level window repaint (as is explicitly advised in the - # Qt documentation) the figure responds very slowly to mouse - # input. The work around is to directly use `repaint` - # (against the advice of the Qt documentation). The - # difference between `update` and repaint is that `update` - # schedules a `repaint` for the next time the system is idle, - # where as `repaint` repaints the window immediately. The - # risk is if `self.draw` gets called with in another `repaint` - # method there will be an infinite recursion. Thus, we only - # expose windows users to this risk. - if sys.platform.startswith('win'): - self._priv_update = self.repaint - else: - self._priv_update = self.update FigureCanvas = FigureCanvasQTAgg