【问题标题】:Matplotlib / PyQT4: transparent figureMatplotlib / PyQT4:透明图
【发布时间】:2013-09-27 11:34:29
【问题描述】:

我正在使用 Python 和 PyQt4,我想在 GUI 中嵌入一个 matplotlib 图。 对我来说重要的是,Figure 的背景与 GUI 的背景颜色相匹配。 (实际情节周围没有灰色背景)

我的部分解决方案是使用以下代码使Figure 透明:

...
fig.patch.set_alpha(0.5)
...

这在 pylab 模式下绘图时效果很好,但是当嵌入 PyQt4 时,重新渲染不会清除旧图,而是在顶部加上我给出的透明度。如下图所示,这是调整窗口大小的结果:

样本是使用code from the matplotlib website 生成的,并在MyMplCanvas__init__ 语句中添加了set_alpha(0.5) 行。

【问题讨论】:

  • 最好将您使用的所有代码粘贴到此处,而不是只提供链接。其他页面可能会发生变化,这会使您的问题不合适。
  • 也将其减少到显示您的问题所需的最低
  • 感谢您的提示。关于减少问题并将其直接发布在 SO 上,您是对的。正是在这种情况下,我想表明即使使用官方配方也会出现问题,而不仅仅是我可能的错误方式。
  • 在这种情况下,我认为正确的做法是将官方代码精简为动态图部分。

标签: python matplotlib pyqt4


【解决方案1】:

您在matplotlib 中发现了一个有趣的错误。 Qt4 后端不会清除它用于在重绘之前显示图形的qImage,因此您会看到阴影。这很容易通过在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

diff 形式的变化:

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

您可以修改本地安装或在代码中对其进行修补。

PR #2449已合并,将在1.3.1中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-19
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多