在绘图屏幕上单击两个点画一条线,然后删除艺术家

时间:2019-05-11 02:44:19

标签: python python-3.x matplotlib plot event-handling

我希望此代码允许我在两个不同位置的绘图屏幕上单击,在每个单击的坐标上绘制“ X”,然后在它们之间绘制一条线。之后,如果我再次单击绘图屏幕,则希望代码删除“ X”散点图和线条。下面的代码在删除行时有问题(用于删除分散项)。它一直返回UnboundLocalError:赋值之前引用的局部变量'l'。有人可以向我解释为什么通过这种方法,remove()方法适用于散点图而不适用于折线图吗?谢谢!

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3], [10,20,30])
p_arts = []
px, py = [], []

def onclick(event):
    if len(p_arts) < 2:
        p = ax.scatter(event.xdata, event.ydata)
        p_arts.append(p)
        px.append(event.xdata)
        py.append(event.ydata)
        if len(p_arts) == 2:
            l = ax.plot(px, py)
    else:
        p_arts[0].remove()
        p_arts[1].remove()
        p_arts.clear()
        px.clear()
        py.clear()
        l.remove()
    fig.canvas.draw()

cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()

1 个答案:

答案 0 :(得分:1)

首先,让我们看一下错误的含义。

它在行l.remove()处引发,表示变量l是在函数中的某个地方定义的,在调用remove时是 but 尚未定义

请注意,l是一个 local 变量,这意味着它的一个实例是在调用函数时创建的,此后销毁了;它不会在调用之间传递。

然后,很明显,由于l仅在if分支中定义,因此如果采用else分支,我们将遇到错误,因为对于该特定调用onclickl不存在。

解决方案就是将其附加到p_arts,就像您为scatterplot艺术家所做的那样。我还将对代码进行一些整理,如下所示:

def onclick(event):
    if len(p_arts) == 0:
        # plot first scatter
        scatter_artist = ax.scatter(event.xdata, event.ydata)
        p_arts.append(scatter_artist)

    elif len(p_arts) == 1:
        # plot second scatter and line
        scatter_artist = ax.scatter(event.xdata, event.ydata)
        p_arts.append(scatter_artist)
        line_artist = ax.plot([event.xdata], [event.ydata])[0]
        p_arts.append(line_artist)

    else:
        # remove everything
        for artist in p_arts:
            artist.remove()

    fig.canvas.draw()