关闭pyplot窗口

44

最终编辑:

关于关闭pyplot窗口的问题,我发现最好不要使用pyplot。SRK在下面的回答中提供了一个处理需要更新的图表的很好的示例。此外,我还发现如何将pyplot图表放入Tkinter窗口中,而Tkinter比pyplot更擅长打开和关闭窗口。这里是如何将pyplot图表放入Tk窗口,还有这是一个很好的示例

我想能够显示多个图表,然后能够从某些代码输入单独关闭(从屏幕上移除)它们,但我不知道如何编写这段代码。

以下是我迄今为止尝试过的。我已经尝试过展示和关闭命令的位置,但唯一真正的结果是其中一个图表没有出现,但我无法将图表从屏幕上移除。我插入了一个raw_input()来创建暂停。

编辑:这些图表是从Tkinter gui调用的,如果有更好的方法从那个方向做这个我会很高兴听到它。

任何意见都将不胜感激,谢谢。

import matplotlib.pyplot as plt

a = range(0,10)
b = range(0,20,2)
c = range(0,30,3)
d = range(0,40,4)

plot1 = plt.figure()
plt.plot(a,b, 'r-o')

plt.show()

plt.close()

plot2 = plt.figure()
plt.plot(c,d, 'b-o')

plt.show()
plt.close() 

编辑代码:这个也没用。

plot1 = plt.figure(1)
plt.plot(a,b, 'r-o')

plot2 = plt.figure(2)
plt.plot(c,d, 'b-o')
#plt.close(1)
#this will prevent plot1 from being displayed
plt.show()
plt.close(1)  # or ('all') or (plot1)
4个回答

84
plt.close()将关闭当前实例。 plt.close(2)将关闭第二个图形。 plt.close(plot1)将关闭名为plot1的图形实例。 plt.close('all')将关闭所有图形。
此处找到更多信息。
请记住,plt.show()是一个阻塞函数,因此在上面使用的示例代码中,直到窗口关闭时才执行plt.close(),这使它变得多余。
您可以在代码开头使用plt.ion()使其变为非阻塞式,但这会产生其他影响。

示例

在我们的评论讨论后,我准备了一个示例来演示如何使用绘图功能。
下面我创建了一个图形:
fig = plt.figure(figsize=plt.figaspect(0.75))
ax = fig.add_subplot(1, 1, 1)
....
par_plot, = plot(x_data,y_data, lw=2, color='red')
在这种情况下,上面的ax是一对坐标轴的句柄。每当我想对这些轴执行操作时,可以通过调用axes(ax)将当前的坐标轴集更改为此特定集。 par_plot是对line2D实例的句柄。这被称为“artist(艺术家)”。如果我想更改线条的属性,例如更改ydata,则可以引用此句柄来进行更改。
我还可以通过以下方式创建滑块小部件:
axsliderA = axes([0.12, 0.85, 0.16, 0.075])
sA = Slider(axsliderA, 'A', -1, 1.0, valinit=0.5)
sA.on_changed(update)

第一行创建一个新的滑块轴(称为axsliderA),第二行创建了放置在该轴上的滑块实例sA,第三行指定了当滑块值更改时要调用的函数(update)。

我的更新函数可能看起来像这样:

def update(val):
    A = sA.val
    B = sB.val
    C = sC.val
    y_data = A*x_data*x_data + B*x_data + C
    par_plot.set_ydata(y_data)
    draw()

par_plot.set_ydata(y_data) 改变了具有句柄 par_plotLine2D对象的 ydata 属性

draw() 函数会更新当前的坐标轴集合。

将它们整合在一起:

from pylab import *
import matplotlib.pyplot as plt
import numpy

def update(val):
    A = sA.val
    B = sB.val
    C = sC.val
    y_data = A*x_data*x_data + B*x_data + C
    par_plot.set_ydata(y_data)
    draw()


x_data = numpy.arange(-100,100,0.1);

fig = plt.figure(figsize=plt.figaspect(0.75))
ax = fig.add_subplot(1, 1, 1)
subplots_adjust(top=0.8)

ax.set_xlim(-100, 100);
ax.set_ylim(-100, 100);
ax.set_xlabel('X')
ax.set_ylabel('Y')

axsliderA = axes([0.12, 0.85, 0.16, 0.075])
sA = Slider(axsliderA, 'A', -1, 1.0, valinit=0.5)
sA.on_changed(update)

axsliderB = axes([0.43, 0.85, 0.16, 0.075])
sB = Slider(axsliderB, 'B', -30, 30.0, valinit=2)
sB.on_changed(update)

axsliderC = axes([0.74, 0.85, 0.16, 0.075])
sC = Slider(axsliderC, 'C', -30, 30.0, valinit=1)
sC.on_changed(update)

axes(ax)
A = 1;
B = 2;
C = 1;
y_data = A*x_data*x_data + B*x_data + C;

par_plot, = plot(x_data,y_data, lw=2, color='red')

show()
关于上述内容的说明:当我运行应用程序时,代码会顺序执行(我认为它将update函数存储在内存中),直到遇到阻塞的show()函数。当您更改其中一个滑块的值时,它会从内存中运行update函数(我认为是这样?)。
这就是为什么实现show()函数的方式是这样的,这样您就可以使用函数在后台更改值来处理数据。

谢谢。那么,这对于我关闭显示的图形有什么意义呢?我想我真正的问题是如何处理plt.show()函数创建的窗口。您有其他处理方法吗? - deadstump
你能给我更多的想法吗?通常我允许用户关闭窗口,或者检测主窗口何时关闭,然后关闭所有窗口。按照你的建议从代码内部关闭窗口并不是很常见。 - stanri
我有一个Tk GUI,当被要求时会生成图形,如果用户需要调整图形,则会调整一些变量并重新生成带有调整的图形。我只想减少用户输入,并在创建新图形之前销毁旧图形,但我猜如果用户必须手动执行此操作,那也不是世界末日。你是说在这种情况下手动操作是可行的吗?谢谢! - deadstump
我尝试使用你提到的plt.ion(),但是使用它时无论是否使用plt.close(),都无法在屏幕上保留图形。而且,如果我使用raw_input(),数据将无法绘制,并且程序会一直挂起,直到我输入数据。这些就是你提到的“其他影响”吗? - deadstump
是的,Python并不适合与plt.ion()一起使用。show()函数有阻塞的原因。我会在答案编辑中详细说明。 - stanri
显示剩余2条评论

10
请使用。
plt.show(block=False)
plt.close('all')

0
对于那些来到这里是因为不想关闭 matplotlib.pyplot,而实际上想要它根本不显示的人,请更改后端。在我的情况下,我使用 Jupytext 来制作 ipynb.py 文件。这样,我希望 .py 文件不打开任何窗口(例如对于 pytest 很有用)。
import sys

if 'ipykernel' not in sys.modules:
    import matplotlib
    matplotlib.use('Agg')  # don't show plot

受到这个答案的启发。

0
使用plt.pause来避免阻塞的提示非常有用!
你可以定义一个小函数,像这样:
def autoclose_plot(t_show_plot=10):
    print(f'automatically closing plot in {t_show_plot}s...')
    plt.pause(t_show_plot)
    plt.close()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接