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 GUI. (no grey background around the actual plot)
My partial solution would be to make the Figure
transparent with the following code:
...
fig.patch.set_alpha(0.5)
...
This works fine when plotting in pylab mode, but when embedding in PyQt4, the re-rendering doesn't clear the old figure, but adds it with on top with transparency I give. As seen in the sample below, which is the result of resizing the window:
The sample was produced using the code from the matplotlib website with adding the set_alpha(0.5)
line in the __init__
statement of MyMplCanvas
.
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
def paintEvent(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 is None:
# 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 QPainter
if 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.py
index 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.