Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_qt5.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
54 changes: 25 additions & 29 deletions lib/matplotlib/backends/backend_qt5agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One concern is that Qt drops some paint events, but that would be surprising.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Qt pulls the rug under us, we're cooked anyways, no?

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)

Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions lib/matplotlib/backends/backend_qt5cairo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down