Python 如何使matplotlib注释在单击打印边界外时消失?

Python 如何使matplotlib注释在单击打印边界外时消失?,python,matplotlib,plot,Python,Matplotlib,Plot,单击数据点时,我使用unutbu的DataCursor代码在matplotlib图上显示注释。(在我的一生中,我找不到与此相关的链接,我在代码中引用的链接也没有指向正确的位置……)问题是,我希望当我在绘图外单击时,它们会消失 def fmt(x, xlabel, y, ylabel) return xlabel+': {x:0.0f}\n'.format(x = x)+ylabel+': {y:0.3f}'.format(y = y) class DataCursor(object):

单击数据点时,我使用unutbu的
DataCursor
代码在
matplotlib
图上显示注释。(在我的一生中,我找不到与此相关的链接,我在代码中引用的链接也没有指向正确的位置……)问题是,我希望当我在绘图外单击时,它们会消失

def fmt(x, xlabel, y, ylabel)
    return xlabel+': {x:0.0f}\n'.format(x = x)+ylabel+': {y:0.3f}'.format(y = y)

class DataCursor(object):
    """A data cursor widget that displays the x,y of a matplotlib artist/plot when it is selected"""

    def annotate(self, ax)
        """ Draws and hides the annotations box for the given axis "ax". """
        annotation = ax.annotate(self.formatter, xy = (0,0), ha = 'right',
                                 xytext = self.offsets, textcoords = 'offset points', va = 'bottom',
                                 bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
                                 arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
        annotation.set_visible(False)
        return annotation

    def __init__(self, artists, x, xlabel, y, ylabel, tolerance = 5, offsets = (-20,20), formatter = fmt, display_all = False):
        """Create the data cursor and connect it to the relevant figure.
        "artists" is the matplotlib artist or sequence of artists that will be selected.
        "tolerance" is the radius (in points) that the mouse click must be within to select the artist.
        "offsets" is a tuple of (x,y) offsets in points from the selected point to the displayed annotation box.
        "formatter" is a callback function which takes 2 numeric arguments and returns a string.
        "display_all" controls whether more than one annotation box will be shown if there are multiple axes. Only one will be shown per axis, regardless.
        """

        self._points = np.column_stack((x,y))
        self.xlabel = xlabel
        self.ylabel = ylabel

        self.formatter = formatter
        self.offsets = offsets
        self.display_all = display_all

        if not cbook.iterable(artists):
            artists = [artists]

        self.artists = artists
        self.axes = tuple(set(art.axes for art in self.artists))
        self.figures = tuple(set(ax.figure for ax in self.axes))

        self.annotations = {}
        for ax in self.axes:
            self.annotations[ax] = self.annotate(ax)

        for artist in self.artists:
            artist.set_picker(tolerance)

        for fig in self.figures:
            fig.canvas.mpl_connect('pick_event', self)


    def snap(self, x, y):
        """ Return the value of in self._points closest to (x,y). """
        values = self.points
        idx = np.nanargmin(((values - (x,y))**2).sum(axis = -1)
        return self._points[idx,:]


    def __call__(self, event):
        """ Intended to be called through "mpl_connect" above. """
        x, y = event.mouseevent.xdata, event.mouseevent.ydata
        annotation = self.annotations[event.artist.axes]

        if x is None:
            for ann in self.annotations.values():
                ann.set_visible(False)
                event.canvas.draw()

        if x is not None:
            if not self.display_all:
                for ann in self.annotations.values():
                    ann.set_visible(False)

            x, y = self.snap(x, y)

            annotation.xy = x, y
            annotation.set_text(self.formatter(x, self.xlabel, y, self.ylabel))
            annotation.set_visible(True)
            annotation.draggable(True)
            event.canvas.draw()
根据文档,我可以使用
artist.set\u picker(tolerance)
中的函数,而不是
tolerance
。这是怎么回事?文档没有很好地解释这一点,我很难找到示例

现在代码的工作方式是,如果我在框外单击,但在数据点的公差范围内,它将使注释消失。如果边缘的公差范围内没有数据,这就让我很不走运。我如何使它,如果我点击绘图灰色区域的任何地方,注释将消失

我认为会让它消失的代码:

    def __call__(self, event):
        """ Intended to be called through "mpl_connect" above. """
        x, y = event.mouseevent.xdata, event.mouseevent.ydata
        annotation = self.annotations[event.artist.axes]

        if x is None:
            for ann in self.annotations.values():
                ann.set_visible(False)
                event.canvas.draw()

您的问题是,您的事件处理函数只侦听与艺术家(AFAIK)固有关联的
'pick\u event'

要实现您想要的,您应该添加另一个侦听器来处理
'button\u press\u event'

这是未经测试的代码,但它应该让您了解:

# in the __init__ code, add:
fig.canvas.mpl_connect('button_press_event', self.clearAnn)

# in the class body:
def clearAnn(self, event):
    if event.inaxes is None:  # event.inaxes returns None if you click outside of the plot area, i.e. in the grey part surrounding the axes
        for ann in self.annotations.values():
            ann.set_visible(False)
            event.canvas.draw()