[英]Matplotlib / PyQT4: transparent figure
I am using Python with PyQt4 and I want to embed a matplotlib figure in the GUI. 我在PyQt4中使用Python,我想在GUI中嵌入一个matplotlib图。 What's important to me, is that the background of the Figure
matches the background color of the GUI. 对我来说重要的是, Figure
的背景与GUI的背景颜色相匹配。 (no grey background around the actual plot) (实际情节周围没有灰色背景)
My partial solution would be to make the Figure
transparent with the following code: 我的部分解决方案是使用以下代码使Figure
透明:
...
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. 这在pylab模式下绘图时效果很好,但是当在PyQt4中嵌入时,重新渲染不会清除旧图形,而是将其添加到我给出的透明度的顶部。 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
. 将样品使用所产生的从matplotlib网站码与添加set_alpha(0.5)
在管线__init__
的语句MyMplCanvas
。
You have found an interesting bug in matplotlib
. 您在matplotlib
发现了一个有趣的错误。 The Qt4
backend does not clear the qImage
it uses to display the figure before redrawing, hence the reason you see the shadows. Qt4
后端不会清除重绘前用于显示图形的qImage
,因此您可以看到阴影的原因。 This is easily fixed by adding a few lines to matplotlib.backends.backed_qt4Agg.FigureCanvasQTAgg.paintEvent
通过向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 PR#2449已合并,将在1.3.1中
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.