Matplotlib / Pyqt4: Transparent Figure
I am using Python with PyQt4 and I want to embed a matplotlib figure in the GUI. What's important to me, is that the background of the Figure matches the background color of the GU
Solution 1:
You have found an interesting bug in matplotlib
. The Qt4
backend does not clear the qImage
it uses to display the figure before redrawing, hence the reason you see the shadows. This is easily fixed by adding a few lines to matplotlib.backends.backed_qt4Agg.FigureCanvasQTAgg.paintEvent
defpaintEvent(self, e):
"""
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
shown onscreen.
"""#FigureCanvasQT.paintEvent(self, e)if DEBUG:
print('FigureCanvasQtAgg.paintEvent: ', self,
self.get_width_height())
if self.blitbox isNone:
# matplotlib is in rgba byte order. QImage wants to put the bytes# into argb format and is in a 4 byte unsigned int. Little endian# system is LSB first and expects the bytes in reverse order# (bgra).if QtCore.QSysInfo.ByteOrder == QtCore.QSysInfo.LittleEndian:
stringBuffer = self.renderer._renderer.tostring_bgra()
else:
stringBuffer = self.renderer._renderer.tostring_argb()
refcnt = sys.getrefcount(stringBuffer)
qImage = QtGui.QImage(stringBuffer, self.renderer.width,
self.renderer.height,
QtGui.QImage.Format_ARGB32)
rect = qImage.rect() ### <-- added this line
p = QtGui.QPainter(self)
p.eraseRect(rect) ### <-- added this line
p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage))
# draw the zoom rectangle to the QPainterif self.drawRect:
p.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.DotLine))
p.drawRect(self.rect[0], self.rect[1],
self.rect[2], self.rect[3])
p.end()
# This works around a bug in PySide 1.1.2 on Python 3.x,# where the reference count of stringBuffer is incremented# but never decremented by QImage.# TODO: revert PR #1323 once the issue is fixed in PySide.del qImage
if refcnt != sys.getrefcount(stringBuffer):
_decref(stringBuffer)
else:
bbox = self.blitbox
l, b, r, t = bbox.extents
w = int(r) - int(l)
h = int(t) - int(b)
t = int(b) + h
reg = self.copy_from_bbox(bbox)
stringBuffer = reg.to_string_argb()
qImage = QtGui.QImage(stringBuffer, w, h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
p = QtGui.QPainter(self)
p.drawPixmap(QtCore.QPoint(l, self.renderer.height-t), pixmap)
p.end()
self.blitbox = None
self.drawRect = False
Changes in diff form:
diff --git a/lib/matplotlib/backends/backend_qt4agg.py b/lib/matplotlib/backends/backend_qt4agg.pyindex 8433731..718d352 100644--- a/lib/matplotlib/backends/backend_qt4agg.py+++ b/lib/matplotlib/backends/backend_qt4agg.py@@ -118,7 +118,9 @@ class FigureCanvasQTAgg(FigureCanvasQT, FigureCanvasAgg):
qImage = QtGui.QImage(stringBuffer, self.renderer.width,
self.renderer.height,
QtGui.QImage.Format_ARGB32)
+ rect = qImage.rect()
p = QtGui.QPainter(self)
+ p.eraseRect(rect)
p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage))
# draw the zoom rectangle to the QPainter
You can either modify your local installation or monkey patch it in your code.
PR #2449 which has been merged and will be in 1.3.1
Post a Comment for "Matplotlib / Pyqt4: Transparent Figure"