2013-09-22 4 views
3

Я использую Python с PyQt4, и я хочу встроить фигуру matplotlib в графический интерфейс. Что для меня важно, так это то, что фон Figure соответствует цвету фона графического интерфейса. (Не серый фон вокруг фактического участка)Matplotlib/PyQT4: прозрачный рисунок

Моего частичным решение не было бы сделать Figure прозрачным с помощью следующего кода:

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

Это прекрасно работает при печати в режиме pylab, но при вложении в PyQt4, повторная рендеринг не очищает старую фигуру, но добавляет ее сверху с прозрачностью, которую я даю. Как видно на приведенном ниже примере, который является результатом изменения размеров окна:

no working sample

Образец, полученный с использованием code from the matplotlib website с добавлением set_alpha(0.5) линию в __init__ заявлении MyMplCanvas.

+0

Лучше всего, чтобы вставить весь код, использованный здесь вместо только предоставление ссылок. Другие страницы могут измениться, что сделает ваш вопрос неправильным. – tacaswell

+0

также сократил его до _minimum_, чтобы показать вашу проблему. – tacaswell

+0

спасибо за подсказки. вы правы в сокращении проблемы и размещении ее непосредственно на SO. Его просто в этом случае я хотел показать, что проблема возникает даже с официальным рецептом, а не только с моим потенциально неправильным способом. – thengineer

ответ

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 --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

Смежные вопросы