如何在Pyqt5环境中使用Pickle保存Matplotlib图形?

如何在Pyqt5环境中使用Pickle保存Matplotlib图形?,matplotlib,pyqt,save,load,pickle,Matplotlib,Pyqt,Save,Load,Pickle,我面临着一个问题,我无法摆脱它。 我试图使用Pickle包来保存matplotlib图,以便在需要时对其进行回复。 到目前为止,我有下面的代码,如果lfpViewer.\uuu Init\uuuu()中的“if”条件为1(我输入0只是为了检查pickle load函数),那么它会打开一个Qt窗口并在其中绘制一些曲线。 因此,我在工具栏上添加了两个按钮,可以在其中保存当前图形的.pickle或从上一个图形加载.pickle import pickle from PyQt5.QtGui import

我面临着一个问题,我无法摆脱它。 我试图使用Pickle包来保存matplotlib图,以便在需要时对其进行回复。 到目前为止,我有下面的代码,如果
lfpViewer.\uuu Init\uuuu()
中的“if”条件为1(我输入0只是为了检查pickle load函数),那么它会打开一个Qt窗口并在其中绘制一些曲线。 因此,我在工具栏上添加了两个按钮,可以在其中保存当前图形的.pickle或从上一个图形加载.pickle

import pickle
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
import os
import matplotlib
import numpy as np
matplotlib.use('Qt5Agg')
import matplotlib.patches as patches
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar


class SurfViewer(QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.centralWidget = QWidget()
        self.color = self.centralWidget.palette().color(QPalette.Background)
        self.setCentralWidget(self.centralWidget)
        self.plotview = QGroupBox(" ")
        self.layout_plotview = QVBoxLayout()
        self.mascenelfp = lfpViewer(self)
        self.layout_plotview.addWidget(self.mascenelfp)
        self.centralWidget.setLayout(self.layout_plotview)


class lfpViewer(QGraphicsView):
    def __init__(self, parent=None):
        super(lfpViewer, self).__init__(parent)
        self.parent=parent
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.setBackgroundBrush(QBrush(self.parent.color))# self.setBackgroundBrush(QBrush(QColor(200, 200, 200)))
        self.figure = plt.figure(facecolor=[self.parent.color.red()/255,self.parent.color.green()/255,self.parent.color.blue()/255]) #Figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self) 
        self.save_button = QPushButton()
        self.save_button.setIcon(QIcon(os.path.join('icons','SaveData.png')))
        self.save_button.setToolTip("Save Figure Data")
        self.toolbar.addWidget(self.save_button)
        self.save_button.clicked.connect(self.saveFigData)
        self.load_button = QPushButton()
        self.load_button.setIcon(QIcon(os.path.join('icons','LoadData.png')))
        self.load_button.setToolTip("Load Figure Data")
        self.toolbar.addWidget(self.load_button)
        self.load_button.clicked.connect(self.loaddatapickle)
        if 0:
            t=np.arange(1000)
            self.axes_l=self.figure.add_subplot(311)
            self.axes_l.plot(t, np.sin(2*3.14*100*t))
            self.axes_Y=self.figure.add_subplot(312)
            self.axes_Y.plot(t, np.cos(2*3.14*100*t))
            self.axes_Yi=self.figure.add_subplot(313)
            self.axes_Yi.plot(t, np.tan(2*3.14*100*t))


        self.canvas.setGeometry(0, 0, 1600, 500 )
        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def loaddatapickle(self):
        fileName = QFileDialog.getOpenFileName(self,'Load Data', '', 'pickle (*.pickle)')
        if  (fileName[0] == '') :
            return
        fileName = str(fileName[0])
        filehandler = open(fileName , 'rb')
        self.figure = pickle.load(filehandler)
        filehandler.close()
        self.canvas.draw()
        self.parent.parent.processEvents()
        return

    def saveFigData(self):
        fileName = QFileDialog.getSaveFileName(self,'Save Figure Data', '', 'pickle (*.pickle)')
        if  (fileName[0] == '') :
            return
        fileName = str(fileName[0])
        file_pi = open(fileName, 'wb')
        pickle.dump(self.figure, file_pi, -1)
        file_pi.close()
        return


def main():
    app = QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.showMaximized()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
保存似乎有效(好吧,至少,我有一个文件),但加载按钮完全没有作用! 即使我有一个.pickle文件,我也不知道pickle是否保存了正确的二进制数字,因为当我在调试模式下加载pickle文件时,我会得到很多红色的东西。 请查看下图:

如果我在不使用PyQt5的情况下编写代码,它可以正常工作,例如,使用以下代码:

import pickle
import matplotlib
import numpy as np
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt 

def loaddatapickle():
    filehandler = open('test.pickle' , 'rb')
    figure = pickle.load(filehandler )
    filehandler.close()
    return  figure

def saveFigData(figure):
    file_pi = open('test.pickle', 'wb')
    pickle.dump(figure , file_pi, 1)
    file_pi.close()
    return


figure = plt.figure( ) #Figure()

Save= 0

if Save==1:
    t=np.arange(1000)
    axes_l=figure.add_subplot(311)
    axes_l.plot(t, np.sin(2*3.14*100*t))
    axes_Y=figure.add_subplot(312)
    axes_Y.plot(t, np.cos(2*3.14*100*t))
    axes_Yi=figure.add_subplot(313)
    axes_Yi.plot(t, np.tan(2*3.14*100*t))
    saveFigData(figure)

else:

    figure=loaddatapickle()
    plt.show()
如果有人知道这里发生了什么,请告诉我!
祝你度过愉快的一天。

我不能确定这是否解决了你面临的问题,但让我们试试看。我需要提到的是,我没有可用的QT5,我正在使用python 2.7和matplotlib 2.0.0。但这里的解决方案可能适用于一般情况

在将程序改编为pyqt4并运行它时,我发现酸洗效果很好。此外,取消勾选不会引发任何错误,因此我怀疑显示未勾选的图形可能有问题

结果表明,允许加载图形的方法不仅是将图形加载到
self.figure
中,而且使用此未拼接的图形重新创建画布,并将其新添加到布局中:

def loaddatapickle(self):
    #needed to change some stuff here, since in Qt4 the dialog directly returns a string
    fileName = QFileDialog.getOpenFileName(self,'Load Data', '' )
    if  (fileName == '') :
        return
    fileName = str(fileName)
    filehandler = open(fileName , 'rb')
    self.figure = pickle.load(filehandler)
    filehandler.close()
    # remove the old canvas
    self.layout().removeWidget(self.canvas)
    # create a new canvas
    self.canvas = FigureCanvas(self.figure)
    # add the new canvas at the position of the old one
    self.layout().addWidget(self.canvas, 1)
    self.canvas.draw()
    self.parent.parent.processEvents()
    return

当然,直接用新图形更新画布会更好,但我还没有找到任何方法。问题可能是因为pickle保存了matplotlib.figure.figure而不是matplotlib.pylab.figure。因此,当我从pickle文件重新加载self.figure时,它无法处理。type(plt.figure())也返回matplotlib.figure.figure,它们都是相同的。