this问题的已接受答案提供了一种在使用nbagg
后端时动态更新Jupyter笔记本中的matplotlib图的方法。但是,此解决方案在循环完成之前不允许与绘图进行任何交互,这意味着您只能与绘图的最终版本进行交互。是否可以在每个更新步骤后与动态更新的图形进行交互?
我想要做的是访问每个图像上的matplotlib事件(在这种情况下是点击次数),然后在X次点击后绘制下一个图像。以下代码适用于qt
后端,但我无法弄清楚如何将其转换为与nbagg
一起使用。目前我可以让事件处理或动态绘图工作,但不能同时进行。
import numpy as np
import time
import matplotlib.pyplot as plt
n_img = 4
img = np.random.rand(20,20,n_img)
fig,ax = plt.subplots()
im = ax.imshow(img[:,:,0])
clicks = []
def onclick(event):
clicks.append(('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
(event.button, event.x, event.y, event.xdata, event.ydata)))
cid = fig.canvas.mpl_connect('button_press_event', onclick)
i = 1
while i < n_img:
plt.pause(0.01)
time.sleep(0.1)
if len(clicks) > 2: # plot next image after 3 clicks
clicks = []
im.set_data(img[:,:,i])
plt.draw()
i += 1
答案 0 :(得分:1)
在与GUI交互时,你真的不应该使用循环。这就是事件处理的目的。您不需要轮询变量,只需让事件处理程序执行必要的操作。
此代码适用于TkAgg
,GTK3Agg
和nbagg
后端:
n_img = 4
img = np.random.rand(20,20,n_img)
fig,ax = plt.subplots()
im = ax.imshow(img[:,:,0])
nclicks = 0
i = 0
plt.title('{} clicks - image #{}'.format(nclicks, i))
def onclick(event):
global nclicks
global i
if nclicks < 2:
nclicks += 1
else:
nclicks = 0
i += 1
im.set_data(img[:,:,i])
if i == n_img - 1:
fig.canvas.mpl_disconnect(cid)
plt.title('{} clicks - image #{}'.format(nclicks, i))
plt.draw() # only necessary with some backends
cid = fig.canvas.mpl_connect('button_press_event', onclick)