РЕДАКТИРОВАТЬ: Основываясь на комментариях ниже, я думаю, что вы ищете курсор на уровне фигуры, который следует за мышью, независимо от осей, над которыми вы зависаете.Я создал новый класс, основанный на коде для MultiCursor
, который должен делать то, что вы хотели.
class FigureCursor(Widget):
def __init__(self, fig, horizOn=True, vertOn=True, useblit=True, **lineprops):
self._cidmotion = None
self._ciddraw = None
self.background = None
self.needclear = False
self.visible = True
self.canvas = fig.canvas
self.fig = fig
self.horizOn = horizOn
self.vertOn = vertOn
self.useblit = useblit
self.vline, = fig.axes[0].plot([.5, .5], [0., 1.], visible=vertOn, transform=self.fig.transFigure,
clip_on = False, **lineprops)
self.hline, = fig.axes[0].plot([0., 1.], [.5, .5], visible=horizOn, transform=self.fig.transFigure,
clip_on=False, **lineprops)
self.connect()
def connect(self):
"""connect events"""
self._cidmotion = self.canvas.mpl_connect('motion_notify_event', self.onmove)
self._ciddraw = self.canvas.mpl_connect('draw_event', self.clear)
def disconnect(self):
"""disconnect events"""
self.canvas.mpl_disconnect(self._cidmotion)
self.canvas.mpl_disconnect(self._ciddraw)
def clear(self, event):
"""clear the cursor"""
if self.ignore(event):
return
if self.useblit:
self.background = (
self.canvas.copy_from_bbox(self.canvas.figure.bbox))
for line in [self.vline, self.hline]:
line.set_visible(False)
def onmove(self, event):
if self.ignore(event):
return
if event.inaxes is None:
return
if not self.canvas.widgetlock.available(self):
return
self.needclear = True
if not self.visible:
return
trans = event.inaxes.transData + self.fig.transFigure.inverted()
x_fig, y_fig = trans.transform([event.xdata, event.ydata])
if self.vertOn:
self.vline.set_xdata([x_fig, x_fig])
self.vline.set_visible(self.visible)
if self.horizOn:
self.hline.set_ydata([y_fig, y_fig])
self.hline.set_visible(self.visible)
self._update()
def _update(self):
if self.useblit:
if self.background is not None:
self.canvas.restore_region(self.background)
if self.vertOn:
self.fig.draw_artist(self.vline)
if self.horizOn:
self.fig.draw_artist(self.hline)
self.canvas.blit(self.canvas.figure.bbox)
else:
self.canvas.draw_idle()
В вашем собственном коде:
(...)
self.multi = FigureCursor(self.figure, horizOn=True, vertOn=True, color='r', lw=1)
(...)

РЕДАКТИРОВАТЬ: часть ниже моя предыдущая попытка ответить на вопрос
Я написал класс, которыйнаследуется от MultiCursor
, и вместо True/False
для horizOn=
и vertOn=
берется список осей, на которых можно рисовать горизонтальные или вертикальные линии.
Я обнаружил поведение MutiCursor
немного странно, когда мышь перемещается от одного топора к другому, но я не изменил это поведение.Этот код должен помочь вам начать дальнейшее изменение класса.В частности, вы можете переопределить функцию onmove()
.

class MyMultiCursor(MultiCursor):
def __init__(self, canvas, axes, useblit=True, horizOn=[], vertOn=[], **lineprops):
super(MyMultiCursor, self).__init__(canvas, axes, useblit=useblit, horizOn=False, vertOn=False, **lineprops)
self.horizAxes = horizOn
self.vertAxes = vertOn
if len(horizOn) > 0:
self.horizOn = True
if len(vertOn) > 0:
self.vertOn = True
xmin, xmax = axes[-1].get_xlim()
ymin, ymax = axes[-1].get_ylim()
xmid = 0.5 * (xmin + xmax)
ymid = 0.5 * (ymin + ymax)
self.vlines = [ax.axvline(xmid, visible=True, **lineprops) for ax in self.vertAxes]
self.hlines = [ax.axhline(ymid, visible=True, **lineprops) for ax in self.horizAxes]
и в своем классе создать экземпляр:
self.multi = MyMultiCursor(self.canvas, (axes, axes2), color='r', lw=1, horizOn=[axes], vertOn=[axes2])