Matplotlib: how to show a figure that has been closed

前端 未结 1 694
陌清茗
陌清茗 2020-11-27 07:13

I have a function which returns a Figure created with pyplot. This function closes the figure before returning it. If I didn\'t close it, showing i

相关标签:
1条回答
  • 2020-11-27 07:50

    When plt.close is called on a figure instance, what is actually destroyed is the graphical interface (the FigureManager) that is used to show the figure on-screen (see comment by JoeKington at Matplotlib: re-open a closed figure?). So the figure instance still exists and has not been destroyed. To show the figure on-screen again, we would have to reconstruct, in some way, an interface to replace the one that has been destroyed when calling plt.close(fig).

    This can be done by simply creating a new figure with plt.figure(), "stealing" its manager, and use it to display the figure that we want to show on-screen. Alternatively, it is possible to reconstruct manually an interface to display the figure with a GUI Toolkit. I provide an example with PySide using the Qt4Agg backend. Moreover, there is a nice example that shows how this can be done with Tkinter (TkAgg) here : http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html (I've tested this approach also and it works).

    Dummy figure approach:

    This solution is based on how to close a show() window but keep the figure alive? and Obtaining the figure manager via the OO interface in Matplotlib. The GUI toolkit that is used to construct the graphical interface for showing the figure on-screen depends on the backend that is used by matplotlib. If the backend used is TkAgg, TkInter will give some warning in Python 2.7 that can be ignored (see this post on python bug tracker).

    import matplotlib.pyplot as plt
    
    def new_figure(): 
    
        fig = plt.figure()
        plt.plot([0, 1], [2, 3])
        plt.close(fig)
        return fig
    
    def show_figure(fig):
    
        # create a dummy figure and use its
        # manager to display "fig"
    
        dummy = plt.figure()
        new_manager = dummy.canvas.manager
        new_manager.canvas.figure = fig
        fig.set_canvas(new_manager.canvas)
    
    if __name__ == '__main__':
    
        fig = new_figure()
        show_figure(fig)
    
        plt.show()
    

    Pyside approach:

    This consists in reconstructing a GUI with a new canvas and toolbar to display the fig instance on-screen.

    Important Note: The code below must be executed in a new dedicated Python console (press F6) if run from Spyder, since Spyder is also a Qt application that starts it's own QApplication (see PySide Qt script doesn't launch from Spyder but works from shell).

    import matplotlib
    matplotlib.use('Qt4Agg')
    matplotlib.rcParams['backend.qt4']='PySide'
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
    from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT
    import matplotlib.pyplot as plt
    
    from PySide import QtGui
    import sys
    
    def new_figure():
    
        fig = plt.figure()
        plt.plot([0, 1], [2, 3])
        plt.close(fig)
        return fig   
    
    class myFigCanvas(QtGui.QWidget):
    
        def __init__(self, fig, parent=None):
            super(myFigCanvas, self).__init__(parent)
    
            #---- create new canvas and toolbar --
    
            canvas = FigureCanvasQTAgg(fig)
            toolbar = NavigationToolbar2QT(canvas, self)
    
            #---- setup layout of GUI ----
    
            grid = QtGui.QGridLayout()    
            grid.addWidget(canvas, 0, 0)
            grid.addWidget(toolbar, 1, 0)
    
            self.setLayout(grid)
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
    
        fig = new_figure()   
        new_canvas = myFigCanvas(fig) 
        new_canvas.show()    
    
        sys.exit(app.exec_())
    

    which results in:

    0 讨论(0)
提交回复
热议问题