如何在后台保持matplotlib(python)窗口?

时间:2017-05-31 07:28:57

标签: python matplotlib background window focus

我有一个python / matplotlib应用程序,经常使用来自测量仪器的新数据更新绘图。使用新数据更新绘图时,绘图窗口不应相对于桌面上的其他窗口从背景更改为前景(反之亦然)。

在运行带有matplotlib 1.5.2rc的Ubuntu 16.10的机器上,Python 3可以正常工作。但是,在使用Ubuntu 17.04和matplotlib 2.0.0的其他计算机上,每次使用新数据更新绘图时,图形窗口会弹出到前面。

如何在使用新数据更新绘图时控制窗口前景/背景行为并保持窗口焦点?

这是一个代码示例,用于说明我的绘图程序:

import matplotlib
import matplotlib.pyplot as plt
from time import time
from random import random

print ( matplotlib.__version__ )

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

# plot things while new data is generated:
t0 = time()
t = []
y = []
while True:
    t.append( time()-t0 )
    y.append( random() )
    fig.clear()
    plt.plot( t , y )
    plt.pause(1)

2 个答案:

答案 0 :(得分:8)

matplotlib从版本1.5.2rc更改为2.0.0,以便pyplot.show()将窗口带到前台(参见here)。因此,关键是要避免在循环中调用pyplot.show()pyplot.pause()也是如此。

以下是一个工作示例。这仍然会在开始时将窗口置于前景。但是用户可以将窗口移动到后台,当用新数据更新图形时窗口将保持在那里。

请注意,matplotlib动画模块可能是生成此示例中显示的绘图的不错选择。但是,我无法使动画与交互式绘图一起工作,因此它会阻止其他代码的进一步执行。这就是我无法在现实生活中使用动画模块的原因。

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

print ( matplotlib.__version__ )

# set up the figure
plt.ion()
fig = plt.figure()
ax = plt.subplot(1,1,1)
ax.set_xlabel('Time')
ax.set_ylabel('Value')
t = []
y = []
ax.plot( t , y , 'ko-' , markersize = 10 ) # add an empty line to the plot
fig.show() # show the window (figure will be in foreground, but the user may move it to background)

# plot things while new data is generated:
# (avoid calling plt.show() and plt.pause() to prevent window popping to foreground)
t0 = time.time()
while True:
    t.append( time.time()-t0 )  # add new x data value
    y.append( random() )        # add new y data value
    ax.lines[0].set_data( t,y ) # set plot data
    ax.relim()                  # recompute the data limits
    ax.autoscale_view()         # automatic axis scaling
    fig.canvas.flush_events()   # update the plot and take care of window events (like resizing etc.)
    time.sleep(1)               # wait for next loop iteration

答案 1 :(得分:0)

对于 tkinter 后端 (matplotlib.use("TkAgg")),使用 flush_events 是不够的:您还需要在每个 fig.canvas.draw_idle() 之前调用 fig.canvas.flush_events()。正如@samlaf 所写,Qt5Agg 后端也是如此。