如何在matplotlib中返回鼠标事件坐标

时间:2014-02-17 00:31:12

标签: python matplotlib interactive

在我的代码中,我定义了一个DraggablePoint类,它支持交互式拖放功能。我还想记录并返回可拖动点的新位置。我可以在事件处理函数中获取它们(通过print),但是如何在main函数中返回值?谢谢你的建议。

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import math

class DraggablePoint:
    lock = None #only one can be animated at a time
    def __init__(self, point):
        self.point = point
        self.press = None
        self.background = None
        self.ax = self.point.figure.add_subplot(111)
        self.final_point = (0.0, 0.0)

    def connect(self):
        'connect to all the events we need'
        self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_press(self, event):
        if event.inaxes != self.point.axes: return
        if DraggablePoint.lock is not None: return
        contains, attrd = self.point.contains(event)
        if not contains: return
        self.press = (self.point.center), event.xdata, event.ydata
        DraggablePoint.lock = self
        print (event.xdata, event.ydata)
        # draw everything but the selected rectangle and store the pixel buffer
        canvas = self.point.figure.canvas
        axes = self.point.axes
        self.point.set_animated(True)
        canvas.draw()
        self.background = canvas.copy_from_bbox(self.point.axes.bbox)

        # now redraw just the rectangle
        axes.draw_artist(self.point)

        # and blit just the redrawn area
        canvas.blit(axes.bbox)

    def on_motion(self, event):
        if DraggablePoint.lock is not self:
            return
        if event.inaxes != self.point.axes: 
            return
        if event.xdata < event.ydata / math.sqrt(3): 
            return
        if event.xdata > (event.ydata - math.sqrt(3))/(-math.sqrt(3)):
            return
        self.point.center, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)

        canvas = self.point.figure.canvas
        axes = self.point.axes
        # restore the background region
        canvas.restore_region(self.background)

        # redraw just the current rectangle
        axes.draw_artist(self.point)

        # blit just the redrawn area
        canvas.blit(axes.bbox)

    def on_release(self, event):
        'on release we reset the press data'
        if DraggablePoint.lock is not self:
            return

        self.press = None
        DraggablePoint.lock = None

        # turn off the rect animation property and reset the background
        self.point.set_animated(False)
        self.background = None
        self.final_point = (event.xdata, event.ydata)
        print (event.xdata, event.ydata)
        # redraw the full figure
        self.point.figure.canvas.draw()


    def disconnect(self):
        'disconnect all the stored connection ids'
        self.point.figure.canvas.mpl_disconnect(self.cidpress)
        self.point.figure.canvas.mpl_disconnect(self.cidrelease)
        self.point.figure.canvas.mpl_disconnect(self.cidmotion)

if __name__ == "__main__":
    fig = plt.figure()
    ax = fig.add_subplot(111)
    point = (0.5, 0.5)
    circle = patches.Circle(point, 0.02, fc='b', alpha=0.5, picker=True)
    draggables = []
    ax.add_patch(circle)
    dr = DraggablePoint(circle)
    dr.connect()
    draggables.append(dr)
    fig.canvas.draw()
    print dr.final_point #this doesn't work
    plt.show()

0 个答案:

没有答案