matplotlib 마우스를 그리는 십자 커서의 실현 (사용자 정의 방식, 공식 실례)
11028 단어 matplotlib마우스커서
widgets 모듈 Cursor 클래스 원본
class Cursor(AxesWidget):
"""
A crosshair cursor that spans the axes and moves with mouse cursor.
For the cursor to remain responsive you must keep a reference to it.
Parameters
----------
ax : `matplotlib.axes.Axes`
The `~.axes.Axes` to attach the cursor to.
horizOn : bool, default: True
Whether to draw the horizontal line.
vertOn : bool, default: True
Whether to draw the vertical line.
useblit : bool, default: False
Use blitting for faster drawing if supported by the backend.
Other Parameters
----------------
**lineprops
`.Line2D` properties that control the appearance of the lines.
See also `~.Axes.axhline`.
Examples
--------
See :doc:`/gallery/widgets/cursor`.
"""
def __init__(self, ax, horizOn=True, vertOn=True, useblit=False,
**lineprops):
AxesWidget.__init__(self, ax)
self.connect_event('motion_notify_event', self.onmove)
self.connect_event('draw_event', self.clear)
self.visible = True
self.horizOn = horizOn
self.vertOn = vertOn
self.useblit = useblit and self.canvas.supports_blit
if self.useblit:
lineprops['animated'] = True
self.lineh = ax.axhline(ax.get_ybound()[0], visible=False, **lineprops)
self.linev = ax.axvline(ax.get_xbound()[0], visible=False, **lineprops)
self.background = None
self.needclear = False
def clear(self, event):
"""Internal event handler to clear the cursor."""
if self.ignore(event):
return
if self.useblit:
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
self.linev.set_visible(False)
self.lineh.set_visible(False)
def onmove(self, event):
"""Internal event handler to draw the cursor when the mouse moves."""
if self.ignore(event):
return
if not self.canvas.widgetlock.available(self):
return
if event.inaxes != self.ax:
self.linev.set_visible(False)
self.lineh.set_visible(False)
if self.needclear:
self.canvas.draw()
self.needclear = False
return
self.needclear = True
if not self.visible:
return
self.linev.set_xdata((event.xdata, event.xdata))
self.lineh.set_ydata((event.ydata, event.ydata))
self.linev.set_visible(self.visible and self.vertOn)
self.lineh.set_visible(self.visible and self.horizOn)
self._update()
def _update(self):
if self.useblit:
if self.background is not None:
self.canvas.restore_region(self.background)
self.ax.draw_artist(self.linev)
self.ax.draw_artist(self.lineh)
self.canvas.blit(self.ax.bbox)
else:
self.canvas.draw_idle()
return False
사용자 정의 십자 커서 구현
간이 십자 커서 구현
먼저 Cursor 클래스의 구조 방법__init__에서 십자 커서의 가로선, 세로선과 좌표 표시를 구성합니다.그리고 on_mouse_move 방법에서 이벤트 데이터에 따라 가로선과 좌표 디스플레이를 업데이트하고 마지막으로 호출할 때 mpl_connect 방법 바인딩 on_mouse_move 메서드 및 마우스 이동 이벤트'motion_unotify_event'.
import matplotlib.pyplot as plt
import numpy as np
class Cursor:
"""
A cross hair cursor.
"""
def __init__(self, ax):
self.ax = ax
self.horizontal_line = ax.axhline(color='k', lw=0.8, ls='--')
self.vertical_line = ax.axvline(color='k', lw=0.8, ls='--')
# text location in axes coordinates
self.text = ax.text(0.72, 0.9, '', transform=ax.transAxes)
def set_cross_hair_visible(self, visible):
need_redraw = self.horizontal_line.get_visible() != visible
self.horizontal_line.set_visible(visible)
self.vertical_line.set_visible(visible)
self.text.set_visible(visible)
return need_redraw
def on_mouse_move(self, event):
if not event.inaxes:
need_redraw = self.set_cross_hair_visible(False)
if need_redraw:
self.ax.figure.canvas.draw()
else:
self.set_cross_hair_visible(True)
x, y = event.xdata, event.ydata
# update the line positions
self.horizontal_line.set_ydata(y)
self.vertical_line.set_xdata(x)
self.text.set_text('x=%1.2f, y=%1.2f' % (x, y))
self.ax.figure.canvas.draw()
x = np.arange(0, 1, 0.01)
y = np.sin(2 * 2 * np.pi * x)
fig, ax = plt.subplots()
ax.set_title('Simple cursor')
ax.plot(x, y, 'o')
cursor = Cursor(ax)
# ,
fig.canvas.mpl_connect('motion_notify_event', cursor.on_mouse_move)
plt.show()
십자 커서 최적화
간편한 구현에서 마우스가 움직일 때마다 전체 그림을 다시 그려서 효율이 비교적 낮다.
최적화 구현에서 마우스가 이동할 때마다 커서와 좌표 디스플레이만 다시 그려지고 배경 이미지는 다시 그려지지 않습니다.
import matplotlib.pyplot as plt
import numpy as np
class BlittedCursor:
"""
A cross hair cursor using blitting for faster redraw.
"""
def __init__(self, ax):
self.ax = ax
self.background = None
self.horizontal_line = ax.axhline(color='k', lw=0.8, ls='--')
self.vertical_line = ax.axvline(color='k', lw=0.8, ls='--')
# text location in axes coordinates
self.text = ax.text(0.72, 0.9, '', transform=ax.transAxes)
self._creating_background = False
ax.figure.canvas.mpl_connect('draw_event', self.on_draw)
def on_draw(self, event):
self.create_new_background()
def set_cross_hair_visible(self, visible):
need_redraw = self.horizontal_line.get_visible() != visible
self.horizontal_line.set_visible(visible)
self.vertical_line.set_visible(visible)
self.text.set_visible(visible)
return need_redraw
def create_new_background(self):
if self._creating_background:
# discard calls triggered from within this function
return
self._creating_background = True
self.set_cross_hair_visible(False)
self.ax.figure.canvas.draw()
self.background = self.ax.figure.canvas.copy_from_bbox(self.ax.bbox)
self.set_cross_hair_visible(True)
self._creating_background = False
def on_mouse_move(self, event):
if self.background is None:
self.create_new_background()
if not event.inaxes:
need_redraw = self.set_cross_hair_visible(False)
if need_redraw:
self.ax.figure.canvas.restore_region(self.background)
self.ax.figure.canvas.blit(self.ax.bbox)
else:
self.set_cross_hair_visible(True)
# update the line positions
x, y = event.xdata, event.ydata
self.horizontal_line.set_ydata(y)
self.vertical_line.set_xdata(x)
self.text.set_text('x=%1.2f, y=%1.2f' % (x, y))
self.ax.figure.canvas.restore_region(self.background)
self.ax.draw_artist(self.horizontal_line)
self.ax.draw_artist(self.vertical_line)
self.ax.draw_artist(self.text)
self.ax.figure.canvas.blit(self.ax.bbox)
x = np.arange(0, 1, 0.01)
y = np.sin(2 * 2 * np.pi * x)
fig, ax = plt.subplots()
ax.set_title('Blitted cursor')
ax.plot(x, y, 'o')
blitted_cursor = BlittedCursor(ax)
fig.canvas.mpl_connect('motion_notify_event', blitted_cursor.on_mouse_move)
plt.show()
데이터 십자 커서 포착 실현
앞의 두 가지 실현에서 마우스 십자 커서는 마음대로 이동할 수 있다.이 구현에서 십자 커서는 마우스 x 좌표에서 가장 가까운 데이터 점에만 나타납니다.
import matplotlib.pyplot as plt
import numpy as np
class SnappingCursor:
"""
A cross hair cursor that snaps to the data point of a line, which is
closest to the *x* position of the cursor.
For simplicity, this assumes that *x* values of the data are sorted.
"""
def __init__(self, ax, line):
self.ax = ax
self.horizontal_line = ax.axhline(color='k', lw=0.8, ls='--')
self.vertical_line = ax.axvline(color='k', lw=0.8, ls='--')
self.x, self.y = line.get_data()
self._last_index = None
# text location in axes coords
self.text = ax.text(0.72, 0.9, '', transform=ax.transAxes)
def set_cross_hair_visible(self, visible):
need_redraw = self.horizontal_line.get_visible() != visible
self.horizontal_line.set_visible(visible)
self.vertical_line.set_visible(visible)
self.text.set_visible(visible)
return need_redraw
def on_mouse_move(self, event):
if not event.inaxes:
self._last_index = None
need_redraw = self.set_cross_hair_visible(False)
if need_redraw:
self.ax.figure.canvas.draw()
else:
self.set_cross_hair_visible(True)
x, y = event.xdata, event.ydata
index = min(np.searchsorted(self.x, x), len(self.x) - 1)
if index == self._last_index:
return # still on the same data point. Nothing to do.
self._last_index = index
x = self.x[index]
y = self.y[index]
# update the line positions
self.horizontal_line.set_ydata(y)
self.vertical_line.set_xdata(x)
self.text.set_text('x=%1.2f, y=%1.2f' % (x, y))
self.ax.figure.canvas.draw()
x = np.arange(0, 1, 0.01)
y = np.sin(2 * 2 * np.pi * x)
fig, ax = plt.subplots()
ax.set_title('Snapping cursor')
line, = ax.plot(x, y, 'o')
snap_cursor = SnappingCursor(ax, line)
fig.canvas.mpl_connect('motion_notify_event', snap_cursor.on_mouse_move)
plt.show()
참고 자료
https://www.matplotlib.org.cn/gallery/misc/cursor_demo_sgskip.html
이 글은 matplotlib에서 마우스를 그리는 십자 커서의 실현(사용자 정의 방식, 공식 실례)에 관한 것입니다. 더 많은 matplotlib 마우스 십자 커서 내용은 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보십시오. 앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
「수리계획법~선형계획법~」을 참고로 matplotlib와 WolframAlpha로 해보고 싶다.(오리지널 포스트) (참고) 선형 계획법 초입문 작업 중입니다. 정수에만 대응합니다. 공부중. 쉽게 3D 표시할 수 있습니까? 조언을 받으면 도움이됩니다. 완성형?을 찾고 있습니다. 잘 부탁드립니다. 정수해: {{x...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.