Обработка событий и выбор
Исходный текст: Event handling and picking
Переводчик: Фейлун
Протокол: CC BY-NC-SA 4.0
Matplotlib использует множество инструментов пользовательского интерфейса (wxpython, tkinter, qt4, gtk и macosx), чтобы поддерживать интерактивное перемещение и масштабирование графиков. У него есть набор API, который позволяет взаимодействовать с графиками через нажатия клавиш и движение мыши, и он «GUI-нейтрален», что очень полезно для разработчиков, так как им не нужно повторять большое количество кода для разных пользовательских интерфейсов. Хотя API обработки событий является GUI-нейтральным, оно основано на модели GTK, которая является первой моделью пользовательского интерфейса, поддерживаемой matplotlib. По сравнению со стандартными событиями GUI, события, которые запускаются, также более разнообразны и включают информацию о том, где произошло событие в matplotlib.axes.Axes
. События также могут понимать систему координат matplotlib и сообщать о положении события в пикселях и координатах данных.
Подключение к событиям
Чтобы получать события, вам нужно написать функцию обратного вызова, а затем подключить вашу функцию к менеджеру событий, который является частью FigureCanvasBase
. Вот простой пример, который печатает местоположение щелчка мышью и какую кнопку нажали:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(np.random.rand(10))
def onclick(event):
print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
(event.button, event.x, event.y, event.xdata, event.ydata))
cid = fig.canvas.mpl_connect('button_press_event', onclick)
FigureCanvas
метод mpl_connect()
возвращает идентификатор соединения, который представляет собой просто целое число. Когда вы хотите разорвать соединение с обратным вызовом, просто вызовите:
fig.canvas.mpl_disconnect(cid)
Обратите внимание, что холст сохраняет только слабую ссылку на обратный вызов. Поэтому, если обратный вызов является методом класса, вам необходимо сохранить ссылку на экземпляр. В противном случае экземпляр будет собран сборщиком мусора, и обратный вызов исчезнет.
Вот список событий, к которым можно подключиться, и описание того, что происходит при возникновении события:
Событие | Класс и описание |
---|---|
'button_press_event' |
MouseEvent — кнопка мыши была нажата |
'button_release_event' |
MouseEvent — кнопка мыши отпущена |
'draw_event' |
DrawEvent — холст рисует график |
'key_press_event' |
KeyEvent — клавиша была нажата |
'key_release_event' |
KeyEvent — клавиша отпущена |
'motion_notify_event' |
MouseEvent — мышь перемещается |
'pick_event' |
PickEvent — объект на холсте был выбран |
'resize_event' |
ResizeEvent — размер холста графика изменился |
'scroll_event' |
MouseEvent — колесо прокрутки мыши было прокручено |
'figure_enter_event' |
LocationEvent — мышь вошла в новый график |
'figure_leave_event' |
LocationEvent — мышь покинула график |
'axes_enter_event' |
LocationEvent — мышь вошла в новую область осей |
'axes_leave_event' |
LocationEvent — мышь покинула область осей |
Свойства событий
Все события matplotlib наследуются от базового класса matplotlib.backend_bases.Event
, который хранит следующие свойства:
name
— имя события;canvas
— экземпляр FigureCanvas
, который сгенерировал событие;guiEvent
— событие GUI, которое вызвало событие matplotlib.Наиболее распространёнными событиями являются события нажатия/отпускания клавиш, нажатия/отпускания и перемещения мыши. Классы KeyEvent
и MouseEvent
, которые обрабатывают эти события, оба наследуют от LocationEvent
, у которого есть следующие свойства:
x
— позиция x, расстояние в пикселях от левого края холста;y
— позиция y, расстояние в пикселях от нижнего края холста;inaxes
— Axes
экземпляр, если мышь прошла через область осей.xdata
— координата x мыши в координатах данных;ydata
— координата y мыши в координатах данных.Но давайте посмотрим на простой пример холста, в котором каждый раз, когда нажимается кнопка мыши, создаётся сегмент линии.
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = list(line.get_xdata())
self.ys = list(line.get_ydata())
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
print('click', event)
if event.inaxes!=self.line.axes: return
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click to build line segments')
line, = ax.plot([0], [0]) # empty line
linebuilder = LineBuilder(line)
plt.show()
Мы только что использовали MouseEvent
, который является LocationEvent
, поэтому мы можем получить доступ к данным и пиксельным координатам в event.x
и event.xdata
. Помимо свойств LocationEvent
, он имеет:
button
— нажатая кнопка, None
, 1, 2, 3, 'up'
, 'down'
('up'
, 'down'
используется для событий прокрутки);key
— нажатая клавиша, None
, любой символ, 'shift'
, 'win'
или 'control'
.Напишите класс перетаскиваемого прямоугольника, инициализированный экземпляром Rectangle
, который можно перетащить, но его положение x
, y
изменяется при перетаскивании. Подсказка: вам нужно сохранить исходное положение xy
прямоугольника и сохранить позицию щелчка мыши в пиксельных координатах при нажатии. При нажатии кнопки мыши проверьте, произошёл ли щелчок внутри вашего прямоугольника (см. matplotlib.patches.Rectangle.contains()
), и сохраните исходное положение прямоугольника xy
и координаты щелчка мыши. В обратном вызове события движения вычислите смещение deltax
и deltay
движения мыши и добавьте эти приращения к сохранённому исходному прямоугольнику и перерисуйте его. В событии отпускания кнопки просто сбросьте все данные о нажатой кнопке на None
.
Здесь решение:
import numpy as np
import matplotlib.pyplot as plt
class DraggableRectangle:
def __init__(self, rect):
self.rect = rect
self.press = None
def connect(self):
'connect to all the events we need'
self.cidpress = self.rect.figure.canvas.mpl_connect(
'button_press_event', self.on_press)
self.cidrelease = self.rect.figure.canvas.mpl_connect(
'button_release_event', self.on_release)
self.cidmotion = self.rect.figure.canvas.mpl_connect(
'motion_notify_event', self.on_motion)
def on_press(self, event):
...
``` **Вычислить среднее значение и стандартное отклонение для 100 массивов данных и построить график зависимости среднего значения от стандартного отклонения. При нажатии на точку (μ, σ) отобразить исходные данные из массива, которые сформировали эти значения.**
Решение задачи:
```py
"""
вычислить среднее значение и стандартное отклонение для 100 наборов данных и построить график зависимости среднего от стандартного отклонения.
При нажатии на одну из точек μ, σ отобразить исходный временной ряд из набора данных, который сформировал эти значения.
"""
import numpy as np
import matplotlib.pyplot as plt
X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('нажмите на точку, чтобы построить временной ряд')
line, = ax.plot(xs, ys, 'o', picker=5) # 5 точек допуска
def onpick(event):
if event.artist!=line: return True
N = len(event.ind)
if not N: return True
figi = plt.figure()
for subplotnum, dataind in enumerate(event.ind):
ax = figi.add_subplot(N,1,subplotnum+1)
ax.plot(X[dataind])
ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
transform=ax.transAxes, va='top')
ax.set_ylim(-0.5, 1.5)
figi.show()
return True
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )