Python matplotlib以我希望的方式工作

Python matplotlib以我希望的方式工作,python,matplotlib,Python,Matplotlib,我不明白用matplotlib创建的图形是如何显示的,何时更新,何时阻塞等等 为了帮助我理解并帮助我让matplotlib做我特别需要的事情,谁能帮我创建一个matplotlib.figure包装器/几乎是克隆的,我们称之为MyFigure,它的行为完全符合下面代码(及其注释)中的描述? X=[0,1] Y=[0,1] Y2a=[0,2] Y2b=[0,2.5] Y3a=[0,3] Y3b=[0,3.5] Y4=[0,4] fig = MyFigure() # Nothing happens

我不明白用matplotlib创建的图形是如何显示的,何时更新,何时阻塞等等

为了帮助我理解并帮助我让matplotlib做我特别需要的事情,谁能帮我创建一个
matplotlib.figure
包装器/几乎是克隆的,我们称之为MyFigure,它的行为完全符合下面代码(及其注释)中的描述?

X=[0,1]
Y=[0,1]
Y2a=[0,2]
Y2b=[0,2.5]
Y3a=[0,3]
Y3b=[0,3.5]
Y4=[0,4]

fig = MyFigure() # Nothing happens
ax=fig.gca() # Nothing happens
ax.plot(X,Y) # Nothing happens
fig.show() # New window (1) appears and shows plot of X,Y; execution continues directly
ax.set_xlabel('X') # Window 1 gets X axis label
ax.set_ylabel('Y') # Window 1 gets Y axis label
fig.hide() # Window 1 disappears
time.sleep(10) # No open windows for 10 seconds 
fig.show() # Window 1 reappears and looks the same as before

fig2 = MyFigure() # Nothing happens
fig2.show() # New window (2) appears and is empty
ax2 = fig2.gca() # Window 2 shows axes
ax2.plot(X,Y2a) # Window 2 shows X,Y2a
fig2.show() # Nothing happens, could be omitted
time.sleep(60) # Long computation. In the meantime, windows 1 and 2 can still be resized and their controls (zoom etc.) can be used
ax2.plot(X,Y2b) # Window 2 shows X,Y2a as well as X,Y2b
fig2.hide() # Window 2 disappears

fig3 = MyFigure() # Nothing happens
ax3 = fig3.gca() # Nothing happens
ax3.plot(X,Y3a) # Nothing happens 
fig3.show() # Window 3 appears and shows plot of X,Y3a; execution continues
fig3.freeze() # Nothing happens, Window 3 is still open and can be manipulated
ax3.set_xlabel('X') # Nothing happens
ax3.set_ylabel('Y') # Nothing happens
fig3.thaw() # Window 3 gets X and Y axis labels 
fig3.clear() # Window 3 is still open but empty
ax3 = fig3.gca() # Window 3 shows empty axes
ax3.plot(X,Y3b) # Window 3 shows plot of X,Y3b

fig4 = MyFigure() # Nothing happens 
ax4 = fig4.gca() # Nothing happens 
ax4.plot(X,Y4) # Nothing happens
fig4.show(block=True) # Window 4 opens and shows X,Y4. Execution pauses 
print('Window 4 was closed by user') # Happens after user closes window 4
fig4.show() # Window 4 reappears and looks as before
fig4.close() # Window 4 disappears and its resources are freed
try:
   fig4.show()
except Exception:
   print('Something went wrong') # Prints 'Something went wrong'

# Windows 1,2,3 still "exist". 
# Window 2 is not visible but could be manipulated and shown again in later code.
# Windows 1 and 3 are still visible and can be manipulated by the user. 
# They disappear as soon as the objects fig and fig3 are garbage collected, 
# or their `hide` or `close` methods are called.
请注意,对
MyFigure().show()
的调用可以做任何您需要的事情。为了让事情如我所描述的那样正常工作,我只使用了
show
这个词,因为它类似于
plt.show
已经做的事情。 我听说至少有三种方法可以帮助我实现一些我想要的关于交互性的东西(
plt.ion()
fig.show(block=False)
plt.draw()
;如果你数一数
ipython
,我不打算使用的魔法命令,三种半),然而,这些都没有像我希望的那样工作,我也不太理解它们背后的逻辑模型。请看问题的底部,了解我失败的尝试

我不想讨论或批评默认情况下matplotlib图形及其方法的工作方式。我确信它们的工作方式有很好的技术和功能上的原因,但它与我的直觉(从其他地方没有真正的GUI经验中得到的)不兼容,而且在学习简单绘图命令之外的任何东西之前,每当我不得不使用它时,我都会对它感到沮丧。我希望改变这一点

基本上,我将
MyFigure
实例想象为使用两个重要的布尔实例变量来表示线程:
visible
freezed
。第一个窗口确定打开的窗口是否与实例关联,并且可以通过
show()
hide()
进行设置;第二个选项控制是立即将更改(例如新打印)添加到绘图区域还是添加到队列,并且可以通过
冻结()
解冻()
进行设置

调用
show(block=False)
只会在用户(或有权访问MyFigure实例的另一个线程)关闭相应窗口后返回。无论当前值是
visible
,都可以调用它,并将导致
visible=False
。调用
saw()
将设置
freezed=False
并将更改队列应用于图形(即使在
visible=False
时也可以应用更改队列,但在该状态下冻结和解冻图形没有意义,除非同时在另一个线程中操作该图形)

对我来说最重要的是
show()
的行为和实例的交互行为;我主要描述了
freeze
行为,以预测在设置中如何处理该用例。我不喜欢
ax=fig.gca()
的行为,使用类似
fig.add(matplotlib.Axes())
的东西会感觉更好,但这与这个问题无关(此外,我相信我自己能解决这个问题)


为了澄清我的挣扎,让我记录下我迄今为止失败的尝试:

plt.ion()

我用

def MyFigure(): 
    plt.ion()
    return plt.figure()
我把第一块注释掉,然后在
fig2=…
继续。 当执行到达time.sleep(60)时,60秒内没有打开的窗口

图显示(块=假)

我记得这篇文章是在我第一次写这篇文章的笔记本电脑上写的,但是在我的台式电脑上使用的matplotlib的较新版本中,block关键字似乎已经被删除了

plt.draw()

这对所有数字都有同等影响。尝试调用
draw
作为
fig
的实例方法会导致
TypeError:draw\u wrapper()缺少1个必需的位置参数:“renderer”

暂时忽略这个问题,
plt.draw()
本身没有任何作用。基于一些互联网研究,我发现后续的
plt.pause(0.01)
符合我的要求。这实际上是最接近我想要的解决方案。如果我将所有
fig.show()
替换为
plt.draw(),则块2完全按照所需工作(忽略最终的
fig.hide()
);plt.pause(0.01)
,但它看起来很丑陋,也不像互联网推荐的那样



(对于潜在的亲密投票者:我可以为代码中的每一行提出一些具体的问题。但是,我觉得所有期望的行为(a)都足够相关,可以一起呈现(b)最好以代码的形式描述,希望将代码与我希望没有的注释一起写。)

老实说,我对网络上的matplotlib教程及其在实践中的使用感到失望。就我个人而言,当我开始以面向对象的方式使用matplotlib时,许多matplotlib的挫折感消失了。而不是做:

from matplotlib.pyplot import *
fig = figure() # implicitly create axis
ax  = gca() 
做:

类似于从中提取此更改

draw()
show()
fig.canvas.draw()
fig.show()

通过这种方式,您可以显式保留特定地物,而不是依赖matplotlib当前聚焦的地物。对我来说,
ion
命令有点神秘,因为我的后端始终是交互式的(qt5/qt4),因此更新体形属性总是会改变它

老实说,我对网络上的matplotlib教程及其在实践中的使用感到失望。就我个人而言,当我开始以面向对象的方式使用matplotlib时,许多matplotlib的挫折感消失了。而不是做:

from matplotlib.pyplot import *
fig = figure() # implicitly create axis
ax  = gca() 
做:

类似于从中提取此更改

draw()
show()
fig.canvas.draw()
fig.show()
通过这种方式,您可以显式保留特定地物,而不是依赖matplotlib当前聚焦的地物。对我来说,
ion
命令有点神秘,因为我的后端总是交互的(qt5/qt4),他