Skip to content Skip to sidebar Skip to footer

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"