簡體   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