Skip to content

Commit 4b1f956

Browse files
authored
Merge pull request #8951 from anntzer/qtagg-blitting
MNT: Let QPaintEvent tell us what region to repaint.
2 parents ac58f1f + 252f413 commit 4b1f956

File tree

3 files changed

+30
-29
lines changed

3 files changed

+30
-29
lines changed

lib/matplotlib/backends/backend_qt5.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ def __init__(self, figure):
241241
self._dpi_ratio_prev = None
242242

243243
self._draw_pending = False
244+
self._erase_before_paint = False
244245
self._is_drawing = False
245246
self._draw_rect_callback = lambda painter: None
246247

@@ -494,6 +495,7 @@ def draw(self):
494495
return
495496
with cbook._setattr_cm(self, _is_drawing=True):
496497
super().draw()
498+
self._erase_before_paint = True
497499
self.update()
498500

499501
def draw_idle(self):

lib/matplotlib/backends/backend_qt5agg.py

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@
1515

1616
class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):
1717

18-
def __init__(self, figure):
19-
super().__init__(figure=figure)
20-
self._bbox_queue = []
21-
22-
def paintEvent(self, e):
18+
def paintEvent(self, event):
2319
"""Copy the image from the Agg canvas to the qt.drawable.
2420
2521
In Qt, all drawing should be done inside of here when a widget is
@@ -37,29 +33,31 @@ def paintEvent(self, e):
3733

3834
painter = QtGui.QPainter(self)
3935

40-
if self._bbox_queue:
41-
bbox_queue = self._bbox_queue
42-
else:
36+
if self._erase_before_paint:
4337
painter.eraseRect(self.rect())
44-
bbox_queue = [
45-
Bbox([[0, 0], [self.renderer.width, self.renderer.height]])]
46-
self._bbox_queue = []
47-
for bbox in bbox_queue:
48-
l, b, r, t = map(int, bbox.extents)
49-
w = r - l
50-
h = t - b
51-
reg = self.copy_from_bbox(bbox)
52-
buf = reg.to_string_argb()
53-
qimage = QtGui.QImage(buf, w, h, QtGui.QImage.Format_ARGB32)
54-
# Adjust the buf reference count to work around a memory leak bug
55-
# in QImage under PySide on Python 3.
56-
if QT_API == 'PySide':
57-
ctypes.c_long.from_address(id(buf)).value = 1
58-
if hasattr(qimage, 'setDevicePixelRatio'):
59-
# Not available on Qt4 or some older Qt5.
60-
qimage.setDevicePixelRatio(self._dpi_ratio)
61-
origin = QtCore.QPoint(l, self.renderer.height - t)
62-
painter.drawImage(origin / self._dpi_ratio, qimage)
38+
self._erase_before_paint = False
39+
40+
rect = event.rect()
41+
left = rect.left()
42+
top = rect.top()
43+
width = rect.width()
44+
height = rect.height()
45+
# See documentation of QRect: bottom() and right() are off by 1, so use
46+
# left() + width() and top() + height().
47+
bbox = Bbox([[left, self.renderer.height - (top + height)],
48+
[left + width, self.renderer.height - top]])
49+
reg = self.copy_from_bbox(bbox)
50+
buf = reg.to_string_argb()
51+
qimage = QtGui.QImage(buf, width, height, QtGui.QImage.Format_ARGB32)
52+
if hasattr(qimage, 'setDevicePixelRatio'):
53+
# Not available on Qt4 or some older Qt5.
54+
qimage.setDevicePixelRatio(self._dpi_ratio)
55+
origin = QtCore.QPoint(left, top)
56+
painter.drawImage(origin / self._dpi_ratio, qimage)
57+
# Adjust the buf reference count to work around a memory
58+
# leak bug in QImage under PySide on Python 3.
59+
if QT_API == 'PySide':
60+
ctypes.c_long.from_address(id(buf)).value = 1
6361

6462
self._draw_rect_callback(painter)
6563

@@ -73,8 +71,6 @@ def blit(self, bbox=None):
7371
if bbox is None and self.figure:
7472
bbox = self.figure.bbox
7573

76-
self._bbox_queue.append(bbox)
77-
7874
# repaint uses logical pixels, not physical pixels like the renderer.
7975
l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds]
8076
t = b + h

lib/matplotlib/backends/backend_qt5cairo.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ def paintEvent(self, event):
3737
# Not available on Qt4 or some older Qt5.
3838
qimage.setDevicePixelRatio(dpi_ratio)
3939
painter = QtGui.QPainter(self)
40+
if self._erase_before_paint:
41+
painter.eraseRect(self.rect())
42+
self._erase_before_paint = False
4043
painter.drawImage(0, 0, qimage)
4144
self._draw_rect_callback(painter)
4245
painter.end()

0 commit comments

Comments
 (0)