From 252f4135799027f9ae887e8fd87e3af906187a22 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 27 Jul 2017 22:32:35 -0700 Subject: [PATCH] Let QPaintEvent tell us what region to repaint. --- lib/matplotlib/backends/backend_qt5.py | 2 + lib/matplotlib/backends/backend_qt5agg.py | 54 ++++++++++----------- lib/matplotlib/backends/backend_qt5cairo.py | 3 ++ 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 0fe2070af3e7..c8f7aaf9434f 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -241,6 +241,7 @@ def __init__(self, figure): self._dpi_ratio_prev = None self._draw_pending = False + self._erase_before_paint = False self._is_drawing = False self._draw_rect_callback = lambda painter: None @@ -494,6 +495,7 @@ def draw(self): return with cbook._setattr_cm(self, _is_drawing=True): super().draw() + self._erase_before_paint = True self.update() def draw_idle(self): diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index ab8cbe4994b3..ca2603bca52c 100644 --- a/lib/matplotlib/backends/backend_qt5agg.py +++ b/lib/matplotlib/backends/backend_qt5agg.py @@ -15,11 +15,7 @@ class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT): - def __init__(self, figure): - super().__init__(figure=figure) - self._bbox_queue = [] - - def paintEvent(self, e): + def paintEvent(self, event): """Copy the image from the Agg canvas to the qt.drawable. In Qt, all drawing should be done inside of here when a widget is @@ -37,29 +33,31 @@ def paintEvent(self, e): painter = QtGui.QPainter(self) - if self._bbox_queue: - bbox_queue = self._bbox_queue - else: + if self._erase_before_paint: painter.eraseRect(self.rect()) - bbox_queue = [ - Bbox([[0, 0], [self.renderer.width, self.renderer.height]])] - self._bbox_queue = [] - for bbox in bbox_queue: - l, b, r, t = map(int, bbox.extents) - w = r - l - h = t - b - reg = self.copy_from_bbox(bbox) - buf = reg.to_string_argb() - qimage = QtGui.QImage(buf, w, h, QtGui.QImage.Format_ARGB32) - # Adjust the buf reference count to work around a memory leak bug - # in QImage under PySide on Python 3. - if QT_API == 'PySide': - ctypes.c_long.from_address(id(buf)).value = 1 - if hasattr(qimage, 'setDevicePixelRatio'): - # Not available on Qt4 or some older Qt5. - qimage.setDevicePixelRatio(self._dpi_ratio) - origin = QtCore.QPoint(l, self.renderer.height - t) - painter.drawImage(origin / self._dpi_ratio, qimage) + self._erase_before_paint = False + + rect = event.rect() + left = rect.left() + top = rect.top() + width = rect.width() + height = rect.height() + # See documentation of QRect: bottom() and right() are off by 1, so use + # left() + width() and top() + height(). + bbox = Bbox([[left, self.renderer.height - (top + height)], + [left + width, self.renderer.height - top]]) + reg = self.copy_from_bbox(bbox) + buf = reg.to_string_argb() + qimage = QtGui.QImage(buf, width, height, QtGui.QImage.Format_ARGB32) + if hasattr(qimage, 'setDevicePixelRatio'): + # Not available on Qt4 or some older Qt5. + qimage.setDevicePixelRatio(self._dpi_ratio) + origin = QtCore.QPoint(left, top) + painter.drawImage(origin / self._dpi_ratio, qimage) + # Adjust the buf reference count to work around a memory + # leak bug in QImage under PySide on Python 3. + if QT_API == 'PySide': + ctypes.c_long.from_address(id(buf)).value = 1 self._draw_rect_callback(painter) @@ -73,8 +71,6 @@ def blit(self, bbox=None): if bbox is None and self.figure: bbox = self.figure.bbox - self._bbox_queue.append(bbox) - # repaint uses logical pixels, not physical pixels like the renderer. l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds] t = b + h diff --git a/lib/matplotlib/backends/backend_qt5cairo.py b/lib/matplotlib/backends/backend_qt5cairo.py index 2544fb203e55..bea4f6069c33 100644 --- a/lib/matplotlib/backends/backend_qt5cairo.py +++ b/lib/matplotlib/backends/backend_qt5cairo.py @@ -37,6 +37,9 @@ def paintEvent(self, event): # Not available on Qt4 or some older Qt5. qimage.setDevicePixelRatio(dpi_ratio) painter = QtGui.QPainter(self) + if self._erase_before_paint: + painter.eraseRect(self.rect()) + self._erase_before_paint = False painter.drawImage(0, 0, qimage) self._draw_rect_callback(painter) painter.end()