Skip to content

Commit dd5424e

Browse files
committed
Let QPaintEvent tell us what region to repaint.
1 parent 300a2a4 commit dd5424e

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

lib/matplotlib/backends/backend_qt5agg.py

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ def __init__(self, figure):
3535
super(FigureCanvasQTAggBase, self).__init__(figure=figure)
3636
self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)
3737
self._agg_draw_pending = False
38-
self._bbox_queue = []
38+
self._bbox_queue = [] # Only kept for backcompatibility, but unused.
39+
self._erase_before_paint = False
3940
self._drawRect = None
4041

4142
def drawRectangle(self, rect):
@@ -50,7 +51,7 @@ def drawRectangle(self, rect):
5051
def blitbox(self):
5152
return self._bbox_queue
5253

53-
def paintEvent(self, e):
54+
def paintEvent(self, event):
5455
"""Copy the image from the Agg canvas to the qt.drawable.
5556
5657
In Qt, all drawing should be done inside of here when a widget is
@@ -83,31 +84,32 @@ def paintEvent(self, e):
8384
if not hasattr(self, 'renderer'):
8485
return
8586

87+
self._bbox_queue.clear()
8688
painter = QtGui.QPainter(self)
87-
88-
if self._bbox_queue:
89-
bbox_queue = self._bbox_queue
90-
else:
89+
rect = event.rect()
90+
left = rect.left()
91+
top = rect.top()
92+
width = rect.width()
93+
height = rect.height()
94+
if self._erase_before_paint:
9195
painter.eraseRect(self.rect())
92-
bbox_queue = [
93-
Bbox([[0, 0], [self.renderer.width, self.renderer.height]])]
94-
self._bbox_queue = []
95-
for bbox in bbox_queue:
96-
l, b, r, t = map(int, bbox.extents)
97-
w = r - l
98-
h = t - b
99-
reg = self.copy_from_bbox(bbox)
100-
buf = reg.to_string_argb()
101-
qimage = QtGui.QImage(buf, w, h, QtGui.QImage.Format_ARGB32)
102-
if hasattr(qimage, 'setDevicePixelRatio'):
103-
# Not available on Qt4 or some older Qt5.
104-
qimage.setDevicePixelRatio(self._dpi_ratio)
105-
origin = QtCore.QPoint(l, self.renderer.height - t)
106-
painter.drawImage(origin / self._dpi_ratio, qimage)
107-
# Adjust the buf reference count to work around a memory
108-
# leak bug in QImage under PySide on Python 3.
109-
if QT_API == 'PySide' and six.PY3:
110-
ctypes.c_long.from_address(id(buf)).value = 1
96+
self._erase_before_paint = False
97+
# See documentation of QRect: bottom() and right() are off by 1, so use
98+
# left() + width() and top() + height().
99+
bbox = Bbox([[left, self.renderer.height - (top + height)],
100+
[left + width, self.renderer.height - top]])
101+
reg = self.copy_from_bbox(bbox)
102+
buf = reg.to_string_argb()
103+
qimage = QtGui.QImage(buf, width, height, QtGui.QImage.Format_ARGB32)
104+
if hasattr(qimage, 'setDevicePixelRatio'):
105+
# Not available on Qt4 or some older Qt5.
106+
qimage.setDevicePixelRatio(self._dpi_ratio)
107+
origin = QtCore.QPoint(left, top)
108+
painter.drawImage(origin / self._dpi_ratio, qimage)
109+
# Adjust the buf reference count to work around a memory
110+
# leak bug in QImage under PySide on Python 3.
111+
if QT_API == 'PySide' and six.PY3:
112+
ctypes.c_long.from_address(id(buf)).value = 1
111113

112114
# draw the zoom rectangle to the QPainter
113115
if self._drawRect is not None:
@@ -125,6 +127,7 @@ def draw(self):
125127
# The Agg draw is done here; delaying causes problems with code that
126128
# uses the result of the draw() to update plot elements.
127129
super(FigureCanvasQTAggBase, self).draw()
130+
self._erase_before_paint = True
128131
self.update()
129132

130133
def draw_idle(self):
@@ -162,7 +165,7 @@ def blit(self, bbox=None):
162165
"""
163166
# If bbox is None, blit the entire canvas. Otherwise
164167
# blit only the area defined by the bbox.
165-
if bbox is None and self.figure:
168+
if bbox is None:
166169
bbox = self.figure.bbox
167170

168171
self._bbox_queue.append(bbox)

0 commit comments

Comments
 (0)