在每次更新时使交互式matplotlib窗口不会弹出到前面(Windows 7)

Dan*_*l F 12 python windows plot matplotlib

今天我将matplotlib升级到版本2.0.2,在未升级可能3年之后.

现在我遇到的问题是,在交互式图中,窗口始终位于前面,就好像这样会使matplotlib绘图窗口弹出,因为活动窗口已成为默认行为.

我该如何停用它?我不希望窗口每隔5秒就出现一次,然后抬起我的文本编辑器,浏览器,......

我希望它保留在我放置它的z顺序中,无论是在活动窗口的前面还是后面.

我相信从2016年1月31日起的以下提交是造成这种有问题的行为的原因:tkagg:提出每个新窗口; 部分地址#596

在Github上找到相关评论https://github.com/matplotlib/matplotlib/issues/596#issuecomment-305298577

似乎是我的电话plt.pause引起了这个问题,而不是plt.plot电话.

Imp*_*est 17

改变后端

问题似乎只出现在使用Tk后端.使用Qt后端,窗口将保持在更新时的位置plt.pause.

要更改后端,请在脚本开头使用这些行.

import matplotlib
matplotlib.use("Qt4agg") # or "Qt5agg" depending on you version of Qt
Run Code Online (Sandbox Code Playgroud)

修改 plt.pause

如果无法更改后端,则以下内容可能会有所帮助.窗口不断弹出的原因来自于内部plt.pause调用plt.show().因此,您pause无需调用即可实现自己的功能show.这需要首先处于交互模式plt.ion(),然后至少一次调用plt.show().之后,您可以使用自定义mypause功能更新绘图,如下所示.

import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from time import time
from random import random

plt.ion()
# set up the figure
fig = plt.figure()
plt.xlabel('Time')
plt.ylabel('Value')

plt.show(block=False)

def mypause(interval):
    backend = plt.rcParams['backend']
    if backend in matplotlib.rcsetup.interactive_bk:
        figManager = matplotlib._pylab_helpers.Gcf.get_active()
        if figManager is not None:
            canvas = figManager.canvas
            if canvas.figure.stale:
                canvas.draw()
            canvas.start_event_loop(interval)
            return


t0 = time()
t = []
y = []
while True:
    t.append( time()-t0 )
    y.append( random() )
    plt.gca().clear()
    plt.plot( t , y )
    mypause(1)
Run Code Online (Sandbox Code Playgroud)

用一个animation.

最后,使用matplotlib.animation类会使上述所有内容都过时.matplotlib页面上matplotlib.animation.FuncAnimation显示一个示例.


Dan*_*ein 9

我在 Mac 上遇到了同样的问题。我不确定这是否是最好的方法,但我没有使用plt.pause(0.001),而是切换fig.canvas.start_event_loop(0.001)到更新动画的每一帧。这允许窗口留在后台。


pep*_*gma 8

现在是 2019 年 4 月,Matplotlib 3.0.3 的 mypause() 函数(从最新的 pyplot 实现中复制)应该看起来更像

import time
import matplotlib.pyplot as plt
def mypause(interval):
    manager = plt._pylab_helpers.Gcf.get_active()
    if manager is not None:
        canvas = manager.canvas
        if canvas.figure.stale:
            canvas.draw_idle()        
        #plt.show(block=False)
        canvas.start_event_loop(interval)
    else:
        time.sleep(interval)
Run Code Online (Sandbox Code Playgroud)

经过一些测试(Qt5 后端/Spyder/Windows 7 64 位),对我有用的调用是:

#plt.pause(0.001) #Brings plot to foreground
#fig.canvas.draw() #Does not work
#plt.draw_all() #Does not work
#plt.draw() #Does not work
#fig.canvas.flush_events() #Updates only if I click the figure 
#import time; time.sleep(0.001) #Does not help flush_events()
#fig.canvas.draw_idle() #Does not work by itself
#fig.canvas.start_event_loop(0.001) #Does not work by itself
#mypause(0.001) #Works!

#Works!
fig.canvas.draw_idle()
fig.canvas.start_event_loop(0.001)
Run Code Online (Sandbox Code Playgroud)

无花果是你的图形对象。在我的情况下,两者中的任何一个都不起作用。根据动画文档,这基本上就是 FuncAnimation 所做的。