如何将 pick 事件回调直接绑定到 matplotlib 中的艺术家

问题描述 投票:0回答:1

我正在一个图中画两条线,我想在单击这些线时画一条垂直线。 我想要的是单击行“y1”时调用回调“on_pick_line1”,单击行 y2 时调用回调“on_pick_line2”。

文档中的所有示例都展示了如何将回调绑定到画布的“on_pick”事件,但它不知道单击了哪一行。

我编写了 Pick_dispatcher 类,它将“on_pick”事件路由到我的回调。该解决方案有效,但在我看来很复杂。

有没有办法将回调“on_pick_line1”直接绑定到行“y1”等等?

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


class Pick_dispatcher():
    """Pick callbacks register themselfs into the dispatcher, then they'll get called"""

    def __init__(self):
        self.callbacks = {}

    def register_callback(self, artist, func):
        self.callbacks[artist] = func

    def unregister_callback(self, artist, func):
        del self.callbacks[artist]

    def __call__(self, event):
        artist = event.artist
        print("Dispatcher calling ", artist.get_label())
        self.callbacks[artist](event)



def on_pick_line1(event):
    artist = event.artist
    i_sel = event.ind                       # list of indexes selected vertices
    i_med = i_sel[len(i_sel) // 2]          # index of median vertex
    x = artist.get_xdata()[i_med]           # median vertex
    ax = artist.axes
    ax.axvline(x, ls='--', lw=1, color='blue')
    artist.get_figure().canvas.draw_idle()



def on_pick_line2(event):
    artist = event.artist
    i_sel = event.ind
    i_med = i_sel[len(i_sel) // 2]
    x = artist.get_xdata()[i_med]
    ax = artist.axes
    ax.axvline(x, ls='--', lw=1, color='red')
    artist.get_figure().canvas.draw_idle()




if __name__ == "__main__":


    # Sample traces
    x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
    y1 = np.array([0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6])
    y2 = np.array([0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5])

    # Prepare plot
    fig, ax = plt.subplots()

    pick_dispatcher = Pick_dispatcher()

    tolerance = 5 # points
    f, = ax.plot(x, y1, marker=".", ms=2, lw=1, label='y1', picker=True, pickradius=tolerance)
    pick_dispatcher.register_callback(f, on_pick_line1)

    g, = ax.plot(x, y2, marker=".", ms=2, lw=1, label='y2', picker=True, pickradius=tolerance)
    pick_dispatcher.register_callback(g, on_pick_line2)

    plt.legend()

    fig.canvas.callbacks.connect('pick_event', pick_dispatcher)
    plt.show()
python matplotlib callback
1个回答
0
投票
import numpy as np
import matplotlib.pyplot as plt

def on_pick_line1(event):
    artist = event.artist
    i_sel = event.ind                       # list of indexes selected vertices
    i_med = i_sel[len(i_sel) // 2]          # index of median vertex
    x = artist.get_xdata()[i_med]           # median vertex
    ax = artist.axes
    ax.axvline(x, ls='--', lw=1, color='blue')
    artist.get_figure().canvas.draw_idle()

def on_pick_line2(event):
    artist = event.artist
    i_sel = event.ind
    i_med = i_sel[len(i_sel) // 2]
    x = artist.get_xdata()[i_med]
    ax = artist.axes
    ax.axvline(x, ls='--', lw=1, color='red')
    artist.get_figure().canvas.draw_idle()

if __name__ == "__main__":
    # Sample traces
    x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
    y1 = np.array([0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6])
    y2 = np.array([0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5])

    # Prepare plot
    fig, ax = plt.subplots()

    tolerance = 5  # points
    line1, = ax.plot(x, y1, marker=".", ms=2, lw=1, label='y1', picker=True, pickradius=tolerance)
    line2, = ax.plot(x, y2, marker=".", ms=2, lw=1, label='y2', picker=True, pickradius=tolerance)

    # Bind callbacks directly
    def on_pick(event):
        if event.artist == line1:
            on_pick_line1(event)
        elif event.artist == line2:
            on_pick_line2(event)

    fig.canvas.mpl_connect('pick_event', on_pick)
    plt.legend()
    plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.