2017-01-26 20 views
2

我面臨一個問題,我無法擺脫它。 我正在嘗試使用Pickle包來保存一個matplotlib圖以重新繪製它,如果我想。 到目前爲止,如果lfpViewer.__Init__()中的'if'條件爲1(我只將0設置爲檢查pickle加載函數),那麼下面的代碼會打開一個Qt窗口並繪製一些曲線。 因此,我在工具欄中添加了兩個按鈕,可以在其中保存當前圖的.pickle或從前一個圖加載.pickle。如何將一個Matplotlib圖與Pickle一起保存在Pyqt5環境中?

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文件時,我得到了很多紅色的東西。 查找下面的圖片:

enter image description here

如果我做不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() 

如果有人有一個想法是什麼正在這裏,請告訴我! 祝您有愉快的一天。

+0

這個問題可能是由於pickle保存了matplotlib.figure.Figure而不是matplotlib.pylab.Figure。所以當我從pickle文件中提取self.figure時,它不能被處理? – ymmx

+0

類型(plt.figure())也返回matplotlib.figure.Figure,它們都是相同的。 – ImportanceOfBeingErnest

回答

1

我不能確定這是否解決了您所面臨的問題,但讓我們試一試。我需要提一下,我沒有QT5,我正在使用python 2.7和matplotlib 2.0.0。但是這裏的解決方案可能適用於一般情況。

將程序調整到pyqt4並運行時,發現酸洗工作正常。此外unpickling沒有拋出任何錯誤,所以我懷疑可能有顯示未撥號的數字的問題。

什麼證明,允許裝載數字不僅是爲了圖加載到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 

當然它直接用新圖形更新畫布會更好,但我還沒有找到任何方法來做到這一點。

+0

男人,這很帥。它完美的作品。 – ymmx

相關問題