Matplotlib:如何显示已关闭的图形

Posted

技术标签:

【中文标题】Matplotlib:如何显示已关闭的图形【英文标题】:Matplotlib: how to show a figure that has been closed 【发布时间】: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()

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

【问题讨论】:

【参考方案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 更多的属性从旧经理复制到新经理可能会起作用,但我还没有解决这个问题。

以上是关于Matplotlib:如何显示已关闭的图形的主要内容,如果未能解决你的问题,请参考以下文章

一行Python代码有多强,可让图形秒变「手绘风」

Python图形之-tkinter与matplotlib结合案例

使用大数据集进行 Matplotlib 图形调整 [关闭]

如何使用 PySide2 在 matplotlib 中显示图形?

R python在无图形用户界面时保存图片

感谢matplotlib,如何在同一图中显示具有重叠数据的多个图形?