Here is an example of two moveable vectors. As we only want to pick and move the end points, two invisible points are added only for the purpose of moving the end points.
This is just a simple example. The motion_notify_callback
can be extended updating many more elements.
Hopefully the names of the functions help enough to figure out what is happening.
from matplotlib import pyplot as plt
from matplotlib.backend_bases import MouseButton
from matplotlib.ticker import MultipleLocator
fig, ax = plt.subplots(figsize=(10, 10))
picked_artist = None
vector_x2 = ax.annotate('', (0, 0), (2, 1), ha="left", va="center",
arrowprops=dict(arrowstyle='<|-', fc="k", ec="k", shrinkA=0, shrinkB=0))
vector_y2 = ax.annotate('', (0, 0), (-1, 2), ha="left", va="center",
arrowprops=dict(arrowstyle='<|-', fc="k", ec="k", shrinkA=0, shrinkB=0))
point_x2, = ax.plot(2, 1, '.', color='none', picker=True)
point_y2, = ax.plot(-1, 2, '.', color='none', picker=True)
def pick_callback(event):
'called when an element is picked'
global picked_artist
if event.mouseevent.button == MouseButton.LEFT:
picked_artist = event.artist
def button_release_callback(event):
'called when a mouse button is released'
global picked_artist
if event.button == MouseButton.LEFT:
picked_artist = None
def motion_notify_callback(event):
'called when the mouse moves'
global picked_artist
if picked_artist is not None and event.inaxes is not None and event.button == MouseButton.LEFT:
picked_artist.set_data([event.xdata], [event.ydata])
if picked_artist == point_x2:
vector_x2.set_position([event.xdata, event.ydata])
elif picked_artist == point_y2:
vector_y2.set_position([event.xdata, event.ydata])
fig.canvas.draw_idle()
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(0.5))
ax.yaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_minor_locator(MultipleLocator(0.5))
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.grid(True, which='major', linestyle='-', lw=1)
ax.grid(True, which='minor', linestyle=':', lw=0.5)
fig.canvas.mpl_connect('button_release_event', button_release_callback)
fig.canvas.mpl_connect('pick_event', pick_callback)
fig.canvas.mpl_connect('motion_notify_event', motion_notify_callback)
plt.show()
