简体   繁体   中英

How to use BytesIO with matplotlib and pyqt5?

I made a graph in matplotlib, and wanted to make it in to an image and use it in my pyqt5 application. Someone suggested I use BytesIO for this. This is my code so far:

Drawing my graph:

...
plt.axis('equal')
buff = io.BytesIO()
plt.savefig(buff, format="png")
print(buff)
return buff

This is then called in another script:

def minionRatioGraphSetup(self, recentMinionRatioAvg):
    image = minionRatioGraph(recentMinionRatioAvg)
    label = QtWidgets.QLabel()
    pixmap = QtGui.QPixmap(image)
    label.setPixmap(pixmap)
    label.setGeometry(QtCore.QRect(0,0,200,200))

It stops working at pixmap = QtGui.QPixmap(image) and I'm unsure why. Also: How could I place this in my MainWindow? because I doubt the code there will work lol

I'm sure there is a solution using a buffer. However, it seems rather complicated to get the byte format correct. So an alternative is to save the image to disk, and then load it from there.

import sys
from PyQt4 import QtGui
import matplotlib.pyplot as plt
import numpy as np

def minionRatioGraph():
    plt.plot([1,3,2])
    plt.savefig(__file__+".png", format="png")


class App(QtGui.QWidget):

    def __init__(self):
        super(App, self).__init__()
        self.setGeometry(300, 300, 250, 150)
        self.setLayout(QtGui.QVBoxLayout())
        label = QtGui.QLabel()
        label2 = QtGui.QLabel("Some other text label") 

        minionRatioGraph()

        qimg = QtGui.QImage(__file__+".png")  
        pixmap = QtGui.QPixmap(qimg)

        label.setPixmap(pixmap)
        self.layout().addWidget(label)
        self.layout().addWidget(label2)
        self.show()


if __name__ == '__main__':
    app = QtGui.QApplication([])
    ex = App()
    sys.exit(app.exec_())

a snippet using pillow, might help avoiding file io

 im = PIL.Image.open("filename")
 with BytesIO() as f:
     im.save(f, format='png')
     f.seek(0)
     image_data = f.read()
     qimg = QImage.fromData(image_data)
     patch_qt = QPixmap.fromImage(qimg)

Here's a solution that only uses the buffer, you need to use PIL to create an ImageQT and then load it to the QPixap

import matplotlib.pyplot as plt
import io
from PIL.ImageQt import ImageQt
from PIL import Image

...

buff = io.BytesIO()
plt.savefig(buff, format="png")
img = Image.open(buff)
img_qt = ImageQt(img)
return img_qt

Then, in your GUI setup, you call your function to return the ImageQT and generate the QPixmap using QPixmap.fromImage()

def minionRatioGraphSetup(self, recentMinionRatioAvg):
    image = minionRatioGraph(recentMinionRatioAvg)
    label = QtWidgets.QLabel()
    pixmap = QtGui.QPixmap.fromImage(image)
    label.setPixmap(pixmap)
    label.setGeometry(QtCore.QRect(0,0,200,200))

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM