【问题标题】:Matplotlib: how to show a figure that has been closedMatplotlib:如何显示已关闭的图形
【发布时间】:2021-07-04 04:01:12
【问题描述】:

我有一个函数,它返回用pyplot 创建的Figure。此函数在返回之前关闭图窗。如果我不关闭它,只需 plt.show() 就可以很容易地显示它,但让我们假设我不能这样做。

我可以轻松地将返回的Figure 保存到一个文件中,但是我找不到显示它的方法(即:有一个显示该图的弹出窗口)。

from matplotlib import pyplot as plt                                                


def new_figure():                                                                   
    fig = plt.figure()                                                              
    plt.plot([0, 1], [2, 3])                                                        
    plt.close(fig)                                                                  
    return fig                                                                      


fig = new_figure()                                                                  
fig.savefig('output.svg')                                                           
fig.show()

我怎样才能显示这个数字?

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    当在figure 实例上调用plt.close 时,实际上被破坏的是用于在屏幕上显示图形的图形界面(FigureManager)(参见 JoeKington 的评论在Matplotlib: re-open a closed figure?)。所以图形实例仍然存在并且没有被销毁。为了再次在屏幕上显示该图形,我们必须以某种方式重建一个接口,以替换在调用plt.close(fig) 时被破坏的接口。

    这可以通过简单地使用plt.figure() 创建一个新图形来完成,“窃取”它的管理器,并使用它来显示我们想要在屏幕上显示的图形。或者,可以手动重建界面以使用 GUI 工具包显示图形。我提供了一个使用 Qt4Agg 后端的 PySide 示例。此外,这里有一个很好的例子,展示了如何使用 Tkinter (TkAgg) 完成此操作:http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html(我也测试过这种方法并且它有效)。

    假人方法:

    此解决方案基于how to close a show() window but keep the figure alive?Obtaining the figure manager via the OO interface in Matplotlib。用于构建在屏幕上显示图形的图形界面的 GUI 工具包依赖于 matplotlib 使用的backend。如果使用的后端是 TkAggTkInter 将在 Python 2.7 中给出一些可以忽略的警告(参见 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 方法:

    这包括使用新的画布和工具栏重建 GUI,以在屏幕上显示 fig 实例。

    重要提示:如果从Spyder 运行,下面的代码必须在新的专用 Python 控制台中执行(按 F6),因为 Spyder 也是一个启动它自己的 QApplication 的 Qt 应用程序(参见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_())
    

    导致:

    【讨论】:

    • mpl 真的应该在figures/figure_managers上有一个'reshow'方法
    • 以防万一其他人遇到这种情况,请注意,虽然这有效,但它会破坏绘图交互性——工具栏(光标位置、缩放等)仍然链接到原始图形,而不是新的一个。我想也许将比 new_manager.canvas.figure = fig 更多的属性从旧经理复制到新经理可能会起作用,但我还没有解决这个问题。
    猜你喜欢
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多