MEP9: Globaler Interaktionsmanager #

Fügen Sie einen globalen Manager für alle Benutzerinteraktionen mit Künstlern hinzu; jeden Künstler in der Größe veränderbar, verschiebbar, hervorhebbar und auswählbar machen, wie es der Benutzer wünscht.

Status #

Diskussion

Branches und Pull-Requests #

https://github.com/dhyams/matplotlib/tree/MEP9

Zusammenfassung #

Das Ziel ist es, mit Matplotlib-Künstlern auf sehr ähnliche Weise interagieren zu können, wie es Zeichenprogramme tun. Gegebenenfalls sollte der Benutzer in der Lage sein, einen Künstler, der sich bereits auf der Leinwand befindet, zu verschieben, in der Größe zu ändern oder auszuwählen. Natürlich hat der Drehbuchautor letztendlich die Kontrolle darüber, ob mit einem Künstler interagiert werden kann oder ob er statisch ist.

Dieser Code dafür wurde bereits privat implementiert und getestet und müsste von seiner aktuellen „Mixin“-Implementierung zu einem echten Teil von Matplotlib migriert werden.

Als Endergebnis stehen matplotlib.artist.Artist vier neue Schlüsselwörter zur Verfügung: _moveable_, _resizeable_, _selectable_ und _highlightable_. Wenn Sie eines dieser Schlüsselwörter auf True setzen, wird die Interaktivität für diesen Künstler aktiviert.

Tatsächlich ist dieses MEP eine logische Erweiterung der Ereignisbehandlung in matplotlib; matplotlib unterstützt bereits Interaktionen auf "niedriger Ebene" wie das Drücken der linken Maustaste, ein Tastendruck oder ähnliches. Das MEP erweitert die Unterstützung auf die logische Ebene, wo Rückrufe an den Künstlern durchgeführt werden, wenn bestimmte interaktive Gesten des Benutzers erkannt werden.

Detaillierte Beschreibung #

Diese neue Funktionalität würde verwendet, um dem Endbenutzer zu ermöglichen, besser mit dem Diagramm zu interagieren. Oft ist ein Diagramm fast das, was der Benutzer möchte, aber eine kleine Neupositionierung und/oder Größenänderung von Komponenten ist notwendig. Anstatt den Benutzer zu zwingen, zum Skript zurückzukehren, um den Speicherort auszuprobieren, wäre einfaches Ziehen und Ablegen angemessen.

Außerdem würde dies Anwendungen besser unterstützen, die matplotlib verwenden; Hier hat der Endbenutzer keinen angemessenen Zugriff oder Wunsch, die zugrunde liegende Quelle zu bearbeiten, um eine Handlung fein abzustimmen. Wenn Matplotlib die Möglichkeit bietet, könnte man hier Künstler auf der Leinwand verschieben oder ihre Größe ändern, um sie an ihre Bedürfnisse anzupassen. Außerdem sollte der Benutzer in der Lage sein, einen Künstler (mit der Maus darüber) zu markieren und ihn mit einem Doppelklick auszuwählen, wenn die Anwendung so etwas unterstützt. In diesem MEP wollen wir auch die Hervorhebung und Auswahl nativ unterstützen; Es liegt an der Bewerbung, was passiert, wenn der Künstler ausgewählt wird. Eine typische Handhabung wäre die Anzeige eines Dialogs zum Bearbeiten der Eigenschaften des Künstlers.

Auch in Zukunft (dies ist nicht Teil dieses MEP) könnte matplotlib Backend-spezifische Eigenschaftsdialoge für jeden Künstler anbieten, die bei der Künstlerauswahl ausgelöst werden. Dieser Abgeordnete wäre ein notwendiges Sprungbrett für diese Fähigkeit.

Derzeit gibt es einige interaktive Möglichkeiten in Matplotlib (z. B. legend.draggable()), aber sie sind in der Regel verstreut und nicht für alle Künstler verfügbar. Dieses MEP versucht, die interaktive Schnittstelle zu vereinheitlichen und für alle Künstler nutzbar zu machen.

Das aktuelle MEP enthält auch Haltegriffe zum Ändern der Größe von Künstlern und entsprechende Kästchen, die gezeichnet werden, wenn Künstler verschoben oder in der Größe geändert werden.

Implementierung #

  • Fügen Sie dem "Baum" von Künstlern geeignete Methoden hinzu, so dass der Interaktivitätsmanager eine konsistente Schnittstelle hat, mit der der Interaktivitätsmanager umgehen kann. Die vorgeschlagenen Methoden, die den Künstlern hinzugefügt werden können, wenn sie die Interaktivität unterstützen sollen, sind:

    • get_pixel_position_ll(self): Ruft die Pixelposition der unteren linken Ecke des Begrenzungsrahmens des Künstlers ab

    • get_pixel_size(self): Ermittelt die Größe des Begrenzungsrahmens des Künstlers in Pixel

    • set_pixel_position_and_size(self,x,y,dx,dy): Setzt die neue Größe des Künstlers so, dass er in den angegebenen Begrenzungsrahmen passt.

  • Hinzufügen der Fähigkeit zu den Backends, um 1) Cursor bereitzustellen, da diese für die visuelle Anzeige des Bewegens/der Größenänderung benötigt werden, und 2) eine Funktion bereitzustellen, die die aktuelle Mausposition ermittelt

  • Implementieren Sie den Manager. Dies wurde bereits privat (von Dhyams) als Mixin durchgeführt und ziemlich viel getestet. Das Ziel wäre, die Funktionalität des Managers in die Künstler zu verschieben, damit sie richtig in Matplotlib ist und nicht als "Monkey-Patch", wie ich es derzeit codiert habe.

Aktuelle Zusammenfassung des Mixins #

(Beachten Sie, dass dieses Mixin vorerst nur privater Code ist, aber offensichtlich zu einem Zweig hinzugefügt werden kann.)

InteractiveArtistMixin:

Mixin-Klasse, um jedes generische Objekt, das auf einer Matplotlib-Leinwand gezeichnet wird, verschiebbar und möglicherweise in der Größe veränderbar zu machen. Das Powerpoint-Modell wird so genau wie möglich befolgt; nicht, weil ich in Powerpoint verliebt bin, sondern weil das die meisten Leute verstehen. Ein Künstler kann auch auswählbar sein, was bedeutet, dass der Künstler bei einem Doppelklick den on_activated() Callback erhält. Schließlich kann ein Künstler hervorhebbar sein, was bedeutet, dass ein Highlight auf den Künstler gezeichnet wird, wenn die Maus darüber fährt. Typischerweise sind hervorhebbare Künstler auch auswählbar, aber das bleibt dem Benutzer überlassen. Grundsätzlich gibt es also vier Attribute, die vom Benutzer pro Künstler eingestellt werden können:

  • hervorheben

  • wählbar

  • beweglich

  • größenveränderbar

Um verschiebbar (ziehbar) oder in der Größe veränderbar zu sein, muss das Objekt, das das Ziel des Mixins ist, die folgenden Protokolle unterstützen:

  • get_pixel_position_ll(selbst)

  • get_pixel_size(selbst)

  • set_pixel_position_and_size(self,x,y,sx,sy)

Beachten Sie, dass nicht in der Größe veränderbare Objekte die Parameter sx und sy ignorieren können. Um hervorgehoben werden zu können, muss das Objekt, das das Ziel des Mixins ist, auch das folgende Protokoll unterstützen:

  • get_highlight(selbst)

Was eine Liste von Künstlern zurückgibt, die verwendet werden, um das Highlight zu zeichnen.

Wenn das Objekt, das das Ziel des Mixins ist, kein Matplotlib-Künstler ist, müssen auch die folgenden Protokolle implementiert werden. Dies ist normalerweise ziemlich trivial, da es irgendwo einen Künstler geben muss , der gezeichnet wird. Normalerweise würde Ihr Objekt diese Anrufe einfach an diesen Künstler weiterleiten.

  • get_figur(selbst)

  • get_axes(selbst)

  • enthält (selbst, Ereignis)

  • set_animated(self,flag)

  • zeichnen (selbst, Renderer)

  • get_visible(selbst)

Die folgenden Benachrichtigungen werden vom Künstler aufgerufen und können optional vom Künstler umgesetzt werden.

  • on_select_begin(selbst)

  • on_select_end(selbst)

  • on_drag_begin(selbst)

  • on_drag_end(selbst)

  • on_activated(selbst)

  • on_highlight(selbst)

  • on_right_click(selbst,Ereignis)

  • on_left_click(selbst,Ereignis)

  • on_middle_click(self,event)

  • on_context_click(self,event)

  • on_key_up(selbst,Ereignis)

  • on_key_down(selbst,Ereignis)

Die folgenden Benachrichtigungen werden auf der Leinwand aufgerufen, wenn kein interaktiver Künstler das Ereignis bearbeitet:

  • on_press(self,event)

  • on_left_click(selbst,Ereignis)

  • on_middle_click(self,event)

  • on_right_click(selbst,Ereignis)

  • on_context_click(self,event)

  • on_key_up(selbst,Ereignis)

  • on_key_down(selbst,Ereignis)

Die folgenden Funktionen, falls vorhanden, können verwendet werden, um das Verhalten des interaktiven Objekts zu ändern:

  • press_filter(self,event) # bestimmt, ob das Objekt das press-Ereignis zu ihm geleitet haben möchte

  • handle_unpicked_cursor() # kann vom Objekt verwendet werden, um einen Cursor zu setzen, wenn der Cursor über das Objekt fährt, wenn es nicht ausgewählt ist.

Unterstützt mehrere Leinwände, wobei eine Ziehsperre, ein Bewegungsmelder und ein globales "aktiviertes" Flag pro Leinwand beibehalten werden. Unterstützt die Größenänderung mit festem Seitenverhältnis, indem die Umschalttaste während der Größenänderung gedrückt gehalten wird.

Bekannte Probleme:

  • Zorder wird während der Auswahl-/Ziehoperationen nicht befolgt. Aufgrund der verwendeten Blit-Technik glaube ich nicht, dass dies behoben werden kann. Die einzige Möglichkeit, die mir einfällt, besteht darin, nach allen Künstlern zu suchen, deren Zorder größer ist als ich, sie alle auf animiert zu setzen und sie dann bei jeder Ziehaktualisierung neu zu zeichnen. Dies kann sehr langsam sein; müssen versuchen.

  • Das Mixin funktioniert nur für wx-Backends aus zwei Gründen: 1) Die Cursor sind fest codiert und 2) es gibt einen Aufruf von wx.GetMousePosition() Diese beiden Mängel werden vernünftigerweise behoben, indem jedes Backend diese Dinge bereitstellt.

Abwärtskompatibilität #

Keine Probleme mit der Abwärtskompatibilität, obwohl es angebracht wäre, einige der vorhandenen interaktiven Funktionen (wie legend.draggable()) zu veralten, sobald diese vorhanden ist.

Alternativen #

Keine, die ich kenne.