繁体   English   中英

如何在 matplotlib 中为交互式绘图创建 onclick(event) 函数的类?

[英]How to make class for onclick(event) functions for Interactive plot in matplotlib?

我尝试使用一些函数创建一个交互式 matplotlib 图。 我想将这些功能分组到一个类中(我对此还很陌生,从别人的代码中得到了帮助)

import matplotlib.pyplot as plt


def draw_line(startx,starty):

    ax = plt.gca()
    xy = plt.ginput(1)
    x = [startx,xy[0][0]]
    y = [starty,xy[0][1]]
    line = ax.plot(x,y, picker=True , pickradius = 5 , color = "blue")
    ax.figure.canvas.draw()        


def onclick(event):

    """
    This implements click functionality.  If it's a double click do something,
    else ignore.
    Once in the double click block, if its a left click, wait for a further 
    click and draw a line between the double click co-ordinates and that click
    (using ginput(1) - the 1 means wait for one mouse input - a higher number
    is used to get multiple clicks to define a polyline)
    """
    ax = plt.gca()

    if event.dblclick:
        if event.button == 1:
            # Draw line
            draw_line(event.xdata,event.ydata) # here you click on the plot
        else:
            pass # Do nothing

    if event.button == 1:
        pass


def onpick(event):    

    ax = plt.gca()

    """

    Handles the pick event - if an object has been picked, store a
    reference to it.  We do this by simply adding a reference to it
    named 'stored_pick' to the axes object.  Note that in python we
    can dynamically add an attribute variable (stored_pick) to an 
    existing object - even one that is produced by a library as in this
    case

    """

    this_artist = event.artist  # the picked object is available as event.artist
    ax.picked_object = this_artist

def on_key(event):

    """
    Function to be bound to the key press event
    If the key pressed is delete and there is a picked object,
    remove that object from the canvas
    """

    if event.key == u'delete':
        ax = plt.gca()
        if ax.picked_object:
            ax.picked_object.remove()
            ax.picked_object = None
            ax.figure.canvas.draw()


def applyplt():

    fig = plt.gcf()
    ax = plt.gca()

    cidonclic = fig.canvas.mpl_connect('button_press_event', onclick)
    cidonpic = fig.canvas.mpl_connect('pick_event', onpick)
    cidonkey = fig.canvas.mpl_connect('key_press_event', on_key)

"""
Basic Plot to test the function.
"""

fig1 = plt.figure(figsize = (10,10))
gs = fig1.add_gridspec(10,10)
ax101 = fig1.add_subplot(gs[:,:])
ax101.set_ylim(0,10)
ax101.set_xlim(0,10)

applyplt()

plt.show()

我想将这些事件函数分组在一个class name(object) (例如: class Drawer(object)

如果可以进行任何其他优化,也请提出建议。 谢谢!

以下是分组到一个类中的函数:

import matplotlib.pyplot as plt


class Interactivity:
    def __init__(self, fig = None):
        self.fig = plt.gcf() if fig is None else fig
        self.ax = self.fig.gca()
        self.connections = ()

    def __enter__(self):
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.disconnect()

    def connect(self):
        """ Install the event handlers for the plot. """
        self.connections = (
            self.fig.canvas.mpl_connect('button_press_event', self.onclick),
            self.fig.canvas.mpl_connect('pick_event', self.onpick),
            self.fig.canvas.mpl_connect('key_press_event', self.on_key),
        )

    def disconnect(self):
        """ Uninstall the event handlers for the plot. """
        for connection in self.connections:
            self.fig.canvas.mpl_disconnect(connection)

    def draw_line(self, startx, starty):
        xy = plt.ginput(1)
        x = [startx, xy[0][0]]
        y = [starty, xy[0][1]]
        self.ax.plot(x, y, picker=True, pickradius=5, color='blue')
        self.ax.figure.canvas.draw()

    def onclick(self, event):
        """
        This implements click functionality. If it's a double click do
        something, else ignore.
        Once in the double click block, if its a left click, wait for a further
        click and draw a line between the double click co-ordinates and that
        click (using ginput(1) - the 1 means wait for one mouse input - a
        higher number is used to get multiple clicks to define a polyline)
        """
        print('onclick')
        if event.dblclick:
            if event.button == 1:
                self.draw_line(event.xdata, event.ydata)


    def onpick(self, event):
        """
        Handles the pick event - if an object has been picked, store a
        reference to it.  We do this by simply adding a reference to it
        named 'picked_object' to the axes object.
        """
        print('onpick')
        this_artist = event.artist
        # the picked object is available as event.artist
        self.ax.picked_object = this_artist

    def on_key(self, event):
        """
        Function to be bound to the key press event
        If the key pressed is delete and there is a picked object,
        remove that object from the canvas
        """
        print('onkey: ', event.key)
        if event.key == 'delete' and self.ax.picked_object:
            self.ax.picked_object.remove()
            self.ax.picked_object = None
            self.ax.figure.canvas.draw()

用法:

# Basic plot to test the functionality
fig = plt.figure(figsize = (10,10))
gs = fig.add_gridspec(10,10)
ax101 = fig.add_subplot(gs[:,:])
ax101.set_ylim(0,10)
ax101.set_xlim(0,10)
with Interactivity():
    plt.show()

如您所见,它可以用作上下文处理程序来自动安装和卸载处理程序,或者您可以创建它的一个实例,然后调用其connect方法手动安装处理程序(然后可选地调用disconnect方法卸载处理程序)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM