Files
notes_estom/Python/matplotlab/gallery/event_handling/pick_event_demo.md
2020-09-26 22:03:11 +08:00

6.4 KiB
Raw Permalink Blame History

选择事件演示

您可以通过设置艺术家的“选择器”属性来启用拾取例如matplotlib Line2DTextPatchPolygonAxesImage等...

选择器属性有多种含义

  • None - 此艺术家对象的选择功能已停用(默认)

  • boolean - 如果为True则启用拾取如果鼠标事件在艺术家上方艺术家将触发拾取事件

  • float - 如果选择器是一个数字则它被解释为以点为单位的epsilon容差如果事件的数据在鼠标事件的epsilon内则艺术家将触发事件。 对于某些艺术家如线条和补丁集合艺术家可能会为生成的挑选事件提供其他数据例如挑选事件的epsilon中的数据索引

  • function - 如果选择器是可调用的,则它是用户提供的函数,用于确定艺术家是否被鼠标事件命中。

    hit, props = picker(artist, mouseevent)

    确定命中测试。 如果鼠标事件在艺术家上方则返回hit = Trueprops是要添加到PickEvent属性的属性字典

通过设置“选取器”属性启用艺术家进行拾取后您需要连接到图形画布pick_event以获取鼠标按下事件的拾取回调。 例如,

def pick_handler(event):
    
    mouseevent = event.mouseevent artist = event.artist # now do something with this...

传递给回调的pick事件matplotlib.backend_bases.PickEvent始终使用两个属性触发

  • mouseevent - 生成拾取事件的鼠标事件。 鼠标事件又具有x和y显示空间中的坐标如左下角的像素和xdataydata数据空间中的坐标等属性。 此外您可以获取有关按下哪些按钮按下哪些键鼠标所在的轴等的信息。有关详细信息请参阅matplotlib.backend_bases.MouseEvent。

  • artist - 生成pick事件的matplotlib.artist。

此外某些艺术家如Line2D和PatchCollection可能会将其他元数据如索引附加到符合选择器条件的数据中例如行中指定的epsilon容差范围内的所有点

以下示例说明了这些方法中的每一种。

选择事件示例

选择事件示例2

选择事件示例3

选择事件示例4

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
from matplotlib.text import Text
from matplotlib.image import AxesImage
import numpy as np
from numpy.random import rand

if 1:  # simple picking, lines, rectangles and text
    fig, (ax1, ax2) = plt.subplots(2, 1)
    ax1.set_title('click on points, rectangles or text', picker=True)
    ax1.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red'))
    line, = ax1.plot(rand(100), 'o', picker=5)  # 5 points tolerance

    # pick the rectangle
    bars = ax2.bar(range(10), rand(10), picker=True)
    for label in ax2.get_xticklabels():  # make the xtick labels pickable
        label.set_picker(True)

    def onpick1(event):
        if isinstance(event.artist, Line2D):
            thisline = event.artist
            xdata = thisline.get_xdata()
            ydata = thisline.get_ydata()
            ind = event.ind
            print('onpick1 line:', zip(np.take(xdata, ind), np.take(ydata, ind)))
        elif isinstance(event.artist, Rectangle):
            patch = event.artist
            print('onpick1 patch:', patch.get_path())
        elif isinstance(event.artist, Text):
            text = event.artist
            print('onpick1 text:', text.get_text())

    fig.canvas.mpl_connect('pick_event', onpick1)

if 1:  # picking with a custom hit test function
    # you can define custom pickers by setting picker to a callable
    # function.  The function has the signature
    #
    #  hit, props = func(artist, mouseevent)
    #
    # to determine the hit test.  if the mouse event is over the artist,
    # return hit=True and props is a dictionary of
    # properties you want added to the PickEvent attributes

    def line_picker(line, mouseevent):
        """
        find the points within a certain distance from the mouseclick in
        data coords and attach some extra attributes, pickx and picky
        which are the data points that were picked
        """
        if mouseevent.xdata is None:
            return False, dict()
        xdata = line.get_xdata()
        ydata = line.get_ydata()
        maxd = 0.05
        d = np.sqrt((xdata - mouseevent.xdata)**2. + (ydata - mouseevent.ydata)**2.)

        ind = np.nonzero(np.less_equal(d, maxd))
        if len(ind):
            pickx = np.take(xdata, ind)
            picky = np.take(ydata, ind)
            props = dict(ind=ind, pickx=pickx, picky=picky)
            return True, props
        else:
            return False, dict()

    def onpick2(event):
        print('onpick2 line:', event.pickx, event.picky)

    fig, ax = plt.subplots()
    ax.set_title('custom picker for line data')
    line, = ax.plot(rand(100), rand(100), 'o', picker=line_picker)
    fig.canvas.mpl_connect('pick_event', onpick2)


if 1:  # picking on a scatter plot (matplotlib.collections.RegularPolyCollection)

    x, y, c, s = rand(4, 100)

    def onpick3(event):
        ind = event.ind
        print('onpick3 scatter:', ind, np.take(x, ind), np.take(y, ind))

    fig, ax = plt.subplots()
    col = ax.scatter(x, y, 100*s, c, picker=True)
    #fig.savefig('pscoll.eps')
    fig.canvas.mpl_connect('pick_event', onpick3)

if 1:  # picking images (matplotlib.image.AxesImage)
    fig, ax = plt.subplots()
    im1 = ax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True)
    im2 = ax.imshow(rand(5, 10), extent=(3, 4, 1, 2), picker=True)
    im3 = ax.imshow(rand(20, 25), extent=(1, 2, 3, 4), picker=True)
    im4 = ax.imshow(rand(30, 12), extent=(3, 4, 3, 4), picker=True)
    ax.axis([0, 5, 0, 5])

    def onpick4(event):
        artist = event.artist
        if isinstance(artist, AxesImage):
            im = artist
            A = im.get_array()
            print('onpick4 image', A.shape)

    fig.canvas.mpl_connect('pick_event', onpick4)


plt.show()

下载这个示例