如何在Pyqt5环境中使用Pickle保存Matplotlib图形?
我面临着一个问题,我无法摆脱它。 我试图使用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
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,它们都是相同的。