Introduction
Ce laboratoire vous guidera à travers un exemple d'application trans-GUI utilisant la gestion d'événements Matplotlib pour interagir avec et modifier des objets sur le canevas. Vous allez apprendre à éditer un tracé sur un graphique, en traînant des marqueurs avec la souris et en basculant leur visibilité.
Conseils sur la VM
Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook pour accéder au Notebook Jupyter pour la pratique.
Parfois, vous devrez peut-être attendre quelques secondes pour que le Notebook Jupyter ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du Notebook Jupyter.
Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.
Importation des bibliothèques
Dans cette étape, nous importons les bibliothèques nécessaires au laboratoire. Nous utilisons Matplotlib pour créer le graphique et gérer les événements.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backend_bases import MouseButton
from matplotlib.patches import PathPatch
from matplotlib.path import Path
Création du graphique
Dans cette étape, nous créons un graphique avec un tracé vert et des bords jaunes, en utilisant les données de tracé fournies. Nous ajoutons ensuite un objet PathPatch au graphique, qui représente le tracé.
fig, ax = plt.subplots()
pathdata = [
(Path.MOVETO, (1.58, -2.57)),
(Path.CURVE4, (0.35, -1.1)),
(Path.CURVE4, (-1.75, 2.0)),
(Path.CURVE4, (0.375, 2.0)),
(Path.LINETO, (0.85, 1.15)),
(Path.CURVE4, (2.2, 3.2)),
(Path.CURVE4, (3, 0.05)),
(Path.CURVE4, (2.0, -0.5)),
(Path.CLOSEPOLY, (1.58, -2.57)),
]
codes, verts = zip(*pathdata)
path = Path(verts, codes)
patch = PathPatch(
path, facecolor='green', edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
Création de la classe PathInteractor
Dans cette étape, nous créons la classe PathInteractor, qui gère les rappels d'événements pour l'objet de tracé. Cette classe nous permet d'éditer le tracé de manière interactive en traînant des marqueurs sur le graphique.
class PathInteractor:
"""
Un éditeur de tracé.
Appuyez sur 't' pour basculer les marqueurs de sommets sur et off. Lorsque les marqueurs de sommets sont activés,
ils peuvent être traînés avec la souris.
"""
showverts = True
epsilon = 5 ## distance maximale en pixels pour considérer qu'un sommet est touché
def __init__(self, pathpatch):
self.ax = pathpatch.axes
canvas = self.ax.figure.canvas
self.pathpatch = pathpatch
self.pathpatch.set_animated(True)
x, y = zip(*self.pathpatch.get_path().vertices)
self.line, = ax.plot(
x, y, marker='o', markerfacecolor='r', animated=True)
self._ind = None ## le sommet actif
canvas.mpl_connect('draw_event', self.on_draw)
canvas.mpl_connect('button_press_event', self.on_button_press)
canvas.mpl_connect('key_press_event', self.on_key_press)
canvas.mpl_connect('button_release_event', self.on_button_release)
canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
self.canvas = canvas
def get_ind_under_point(self, event):
"""
Retourne l'index du point le plus proche de la position de l'événement ou *None*
si aucun point n'est à moins de ``self.epsilon`` de la position de l'événement.
"""
xy = self.pathpatch.get_path().vertices
xyt = self.pathpatch.get_transform().transform(xy) ## en coordonnées d'affichage
xt, yt = xyt[:, 0], xyt[:, 1]
d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
ind = d.argmin()
return ind if d[ind] < self.epsilon else None
def on_draw(self, event):
"""Rappel pour les dessins."""
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
self.ax.draw_artist(self.pathpatch)
self.ax.draw_artist(self.line)
self.canvas.blit(self.ax.bbox)
def on_button_press(self, event):
"""Rappel pour les pressions de bouton de souris."""
if (event.inaxes is None
or event.button!= MouseButton.LEFT
or not self.showverts):
return
self._ind = self.get_ind_under_point(event)
def on_button_release(self, event):
"""Rappel pour les relâches de bouton de souris."""
if (event.button!= MouseButton.LEFT
or not self.showverts):
return
self._ind = None
def on_key_press(self, event):
"""Rappel pour les pressions de touches."""
if not event.inaxes:
return
if event.key == 't':
self.showverts = not self.showverts
self.line.set_visible(self.showverts)
if not self.showverts:
self._ind = None
self.canvas.draw()
def on_mouse_move(self, event):
"""Rappel pour les déplacements de souris."""
if (self._ind is None
or event.inaxes is None
or event.button!= MouseButton.LEFT
or not self.showverts):
return
vertices = self.pathpatch.get_path().vertices
vertices[self._ind] = event.xdata, event.ydata
self.line.set_data(zip(*vertices))
self.canvas.restore_region(self.background)
self.ax.draw_artist(self.pathpatch)
self.ax.draw_artist(self.line)
self.canvas.blit(self.ax.bbox)
Création de l'interacteur de tracé
Dans cette étape, nous créons une instance de la classe PathInteractor, en passant l'objet PathPatch que nous avons créé précédemment.
interactor = PathInteractor(patch)
Définir les propriétés du graphique
Dans cette étape, nous définissons le titre et les limites des axes pour le graphique.
ax.set_title('drag vertices to update path')
ax.set_xlim(-3, 4)
ax.set_ylim(-3, 4)
Afficher le graphique
Dans cette étape, nous affichons le graphique à l'écran.
plt.show()
Sommaire
Dans ce laboratoire, nous avons appris à créer un graphique interactif qui nous permet d'éditer un tracé en traînant des marqueurs sur le graphique. Nous avons utilisé la bibliothèque Matplotlib pour créer le graphique et gérer les événements, et avons créé une classe personnalisée pour gérer les rappels d'événements. En suivant ces étapes, vous pouvez créer vos propres graphiques interactifs avec Matplotlib.