Interaktive Bearbeitung der Matplotlib-Leinwand

PythonPythonBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab führen wir Sie durch ein Beispiel einer cross-GUI-Anwendung, bei der Matplotlib-Ereignisbehandlung verwendet wird, um mit Objekten auf der Leinwand zu interagieren und zu modifizieren. Sie werden lernen, wie Sie einen Pfad auf einem Graphen bearbeiten, indem Sie Marker mit der Maus ziehen und deren Sichtbarkeit umschalten.

Tipps für die VM

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu öffnen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund von Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.

Bibliotheken importieren

In diesem Schritt importieren wir die erforderlichen Bibliotheken für das Lab. Wir verwenden Matplotlib, um den Graphen zu erstellen und Ereignisse zu verarbeiten.

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

Den Graphen erstellen

In diesem Schritt erstellen wir einen Graphen mit einem grünen Pfad und gelben Kanten, indem wir die bereitgestellten Pfaddaten verwenden. Anschließend fügen wir ein PathPatch-Objekt zum Graphen hinzu, das den Pfad darstellt.

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)

Die PathInteractor-Klasse erstellen

In diesem Schritt erstellen wir die PathInteractor-Klasse, die die Ereignisrufe für das Pfadobjekt behandelt. Diese Klasse ermöglicht es uns, den Pfad interaktiv zu bearbeiten, indem wir Marker auf dem Graphen ziehen.

class PathInteractor:
    """
    Ein Pfad-Editor.

    Drücken Sie 't', um die Eckmarkierungen an- und auszuschalten. Wenn die Eckmarkierungen aktiviert sind,
    können Sie sie mit der Maus ziehen.
    """

    showverts = True
    epsilon = 5  ## maximale Pixelabstand, um als Eckpunkt-Treffer zu gelten

    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  ## der aktive Eckpunkt

        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):
        """
        Gibt den Index des Punkts zurück, der am nächsten an der Ereignisposition liegt, oder *None*,
        wenn kein Punkt innerhalb von ``self.epsilon`` zur Ereignisposition liegt.
        """
        xy = self.pathpatch.get_path().vertices
        xyt = self.pathpatch.get_transform().transform(xy)  ## in die Anzeige-Koordinaten
        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):
        """Ruf für Zeichnungen."""
        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):
        """Ruf für Mausklick-Ereignisse."""
        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):
        """Ruf für Maus loslassen-Ereignisse."""
        if (event.button!= MouseButton.LEFT
                or not self.showverts):
            return
        self._ind = None

    def on_key_press(self, event):
        """Ruf für Tastendrücke."""
        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):
        """Ruf für Mausbewegungen."""
        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)

Den Pfad-Interaktor erstellen

In diesem Schritt erstellen wir eine Instanz der PathInteractor-Klasse und übergeben das zuvor erstellte PathPatch-Objekt.

interactor = PathInteractor(patch)

Diagrammeigenschaften festlegen

In diesem Schritt legen wir den Titel und die Achsengrenzen für das Diagramm fest.

ax.set_title('drag vertices to update path')
ax.set_xlim(-3, 4)
ax.set_ylim(-3, 4)

Zeige das Diagramm an

In diesem Schritt zeigen wir das Diagramm auf dem Bildschirm an.

plt.show()

Zusammenfassung

In diesem Lab haben wir gelernt, wie man ein interaktives Diagramm erstellt, das es uns ermöglicht, einen Pfad durch Ziehen von Markern auf dem Diagramm zu bearbeiten. Wir haben die Matplotlib-Bibliothek verwendet, um das Diagramm zu erstellen und Ereignisse zu behandeln, und eine benutzerdefinierte Klasse erstellt, um die Ereignisrufe zu behandeln. Indem Sie diese Schritte befolgen, können Sie Ihre eigenen interaktiven Diagramme mit Matplotlib erstellen.