matplotlib
官方除了提供了鼠标十字光标的示例,还提供了同一图像内多子图共享光标的示例,其功能主要由widgets
模块中的MultiCursor
类提供支持。
MultiCursor
类与Cursor
类参数类似,差异主要在:
Cursor
类参数只有一个ax
,即需要显示光标的子图;MultiCursor
类参数为canvas
和axes
,其中axes
为需要共享光标的子图列表。Cursor
类中,光标默认是十字线;MultiCursor
类中,光标默认为竖线。
官方示例
import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.widgets import MultiCursort = np.arange(0.0, 2.0, 0.01)s1 = np.sin(2*np.pi*t)s2 = np.sin(4*np.pi*t)fig, (ax1, ax2) = plt.subplots(2, sharex=True)ax1.plot(t, s1)ax2.plot(t, s2)multi = MultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1)plt.show()
简易修改版
multi = MultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1, horizOn=True, vertOn=True)
MultiCursor
类源码
class MultiCursor(Widget):"""Provide a vertical (default) and/or horizontal line cursor shared betweenmultiple axes.For the cursor to remain responsive you must keep a reference to it.Example usage::from matplotlib.widgets import MultiCursorimport matplotlib.pyplot as pltimport numpy as npfig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)t = np.arange(0.0, 2.0, 0.01)ax1.plot(t, np.sin(2*np.pi*t))ax2.plot(t, np.sin(4*np.pi*t))multi = MultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1,horizOn=False, vertOn=True)plt.show()"""def __init__(self, canvas, axes, useblit=True, horizOn=False, vertOn=True,**lineprops):self.canvas = canvasself.axes = axesself.horizOn = horizOnself.vertOn = vertOnxmin, xmax = axes[-1].get_xlim()ymin, ymax = axes[-1].get_ylim()xmid = 0.5 * (xmin + xmax)ymid = 0.5 * (ymin + ymax)self.visible = Trueself.useblit = useblit and self.canvas.supports_blitself.background = Noneself.needclear = Falseif self.useblit:lineprops['animated'] = Trueif vertOn:self.vlines = [ax.axvline(xmid, visible=False, **lineprops)for ax in axes]else:self.vlines = []if horizOn:self.hlines = [ax.axhline(ymid, visible=False, **lineprops)for ax in axes]else:self.hlines = []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):returnif self.useblit:self.background = (self.canvas.copy_from_bbox(self.canvas.figure.bbox))for line in self.vlines + self.hlines:line.set_visible(False)def onmove(self, event):if self.ignore(event):returnif event.inaxes is None:returnif not self.canvas.widgetlock.available(self):returnself.needclear = Trueif not self.visible:returnif self.vertOn:for line in self.vlines:line.set_xdata((event.xdata, event.xdata))line.set_visible(self.visible)if self.horizOn:for line in self.hlines:line.set_ydata((event.ydata, event.ydata))line.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:for ax, line in zip(self.axes, self.vlines):ax.draw_artist(line)if self.horizOn:for ax, line in zip(self.axes, self.hlines):ax.draw_artist(line)self.canvas.blit()else:self.canvas.draw_idle()