与Jupyter笔记本

时间:2016-06-25 11:07:25

标签: python matplotlib jupyter-notebook

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

1 个答案:

答案 0 :(得分:1)

在与GUI交互时,你真的不应该使用循环。这就是事件处理的目的。您不需要轮询变量,只需让事件处理程序执行必要的操作。

此代码适用于TkAggGTK3Aggnbagg后端:

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)