mpl-gui Dokumentation#
Motivation#
Dieses Projekt ist ein Prototypenbereich zur Überarbeitung der GUI-Ereignisschleifen-Management-Tools, die Matplotlib in pyplot bereitstellt.
Das pyplot-Modul dient derzeit zwei kritischen, aber nicht miteinander verbundenen Funktionen
Bereitstellung einer zustandsbehafteten impliziten API, die MATLAB ähnelt / von MATLAB inspiriert wurde
Bereitstellung des Managements der Interaktion zwischen Matplotlib und der GUI-Ereignisschleife, einschließlich des Aufrechterhaltens von Figures
Obwohl dies bei der Arbeit an der Eingabeaufforderung sehr praktisch sein kann, kann die zustandsbehaftete API zu fragilem Code führen, der auf verwirrende Weise vom globalen Zustand abhängt, insbesondere wenn er in Bibliotheks-Code verwendet wird. Andererseits leistet matplotlib.pyplot sehr gute Arbeit, um dem Benutzer zu verbergen, dass er eine GUI-Anwendung entwickelt, und kümmert sich zusammen mit IPython um viele der Details, die beim parallelen Ausführen einer GUI-Anwendung mit Python anfallen.
Beispiele#
Wenn Sie sicher sein wollen, dass dieser Code nicht heimlich von pyplot abhängt, führen Sie
import sys
sys.modules['matplotlib.pyplot'] = None
was verhindert, dass pyplot importiert wird!
anzeigen#
Der Kern der API ist show
import mpl_gui as mg
from matplotlib.figure import Figure
fig1 = Figure(label='A Label!')
fig2 = Figure()
mg.show([fig1, fig2])
was sowohl Figures anzeigen als auch blockieren wird, bis sie geschlossen werden. Als Teil des „Anzeigeprozesses“ werden die korrekten GUI-Objekte erstellt, auf dem Bildschirm angezeigt und die Ereignisschleife des Host-GUI-Frameworks wird ausgeführt.
blockierend (oder nicht)#
Ähnlich wie plt.ion und plt.ioff stellen wir mg.ion() und mg.ioff() bereit, die identische Semantik haben. Somit
import mpl_gui as mg
from matplotlib.figure import Figure
mg.ion()
print(mg.is_interactive())
fig = Figure()
mg.show([fig]) # will not block
mg.ioff()
print(mg.is_interactive())
mg.show([fig]) # will block!
Wie bei plt.show können Sie das blockierende Verhalten von mg.show explizit über das Schlüsselwortargument block steuern
import mpl_gui as mg
from matplotlib.figure import Figure
fig = Figure(label='control blocking')
mg.show([fig], block=False) # will never block
mg.show([fig], block=True) # will always block
Der interaktive Zustand wird von Matplotlib geteilt und kann auch mit matplotlib.interactive gesteuert und über matplotlib.is_interactive abgefragt werden.
Figuren- und Axes-Erstellung#
In Analogie zu matplotlib.pyplot stellen wir auch figure, subplots und subplot_mosaic bereit
import mpl_gui as mg
fig1 = mg.figure()
fig2, axs = mg.subplots(2, 2)
fig3, axd = mg.subplot_mosaic('AA\nBC')
mg.show([fig1, fig2, fig3])
Wenn mpl_gui im „interaktiven Modus“ ist, werden mpl_gui.figure, mpl_gui.subplots und mpl_gui.subplot_mosaic die neue Figure automatisch in einem Fenster auf dem Bildschirm anzeigen (aber die Ereignisschleife nicht ausführen).
FigureRegistry#
In den obigen Beispielen liegt es in der Verantwortung des Benutzers, die erstellten Figure-Instanzen zu verfolgen. Wenn der Benutzer keine harte Referenz auf das fig-Objekt hält, entweder direkt oder indirekt über seine Kinder, wird es wie jedes andere Python-Objekt vom Garbage Collector bereinigt. Dies kann zwar in einigen Fällen von Vorteil sein (z. B. bei Skripten oder Funktionen, die viele transiente Figures erstellen). Es verliert die Bequemlichkeit, dass matplotlib.pyplot die Instanzen für Sie verwaltet. Zu diesem Zweck haben wir auch FigureRegistry bereitgestellt.
import mpl_gui as mg
fr = mg.FigureRegistry()
fr.figure()
fr.subplots(2, 2)
fr.subplot_mosaic('AA\nBC')
fr.show_all() # will show all three figures
fr.show() # alias for pyplot compatibility
fr.close_all() # will close all three figures
fr.close('all') # alias for pyplot compatibility
Wenn Sie also nur diesen eingeschränkten Satz der pyplot-API verwenden, können Sie ändern
import matplotlib.pyplot as plt
zu
import mpl_gui as mg
plt = mg.FigureRegistry()
und haben einen (weitgehend) Drop-in-Ersatz.
Zusätzlich gibt es ein FigureRegistry.by_label-Hilfsobjekt, das ein Wörterbuch zurückgibt, das die Beschriftungen der Figures jeweils einer Figure zuordnet.
import mpl_gui as mg
fr = mg.FigureRegistry()
figA = fr.figure(label='A')
figB = fr.subplots(2, 2, label='B')
fr.by_label['A'] is figA
fr.by_label['B'] is figB
FigureContext#
Ein sehr häufiger Anwendungsfall ist die Erstellung mehrerer Figures und deren gemeinsame Anzeige am Ende. Um dies zu erleichtern, stellen wir eine Unterklasse von FigureRegistry bereit, die als Kontextmanager verwendet werden kann, der die erstellten Figures (lokal) verfolgt und sie beim Beenden anzeigt.
import mpl_gui as mg
with mg.FigureContext() as fc:
fc.subplot_mosaic('AA\nBC')
fc.figure()
fc.subplots(2, 2)
Dies erstellt 3 Figures und blockiert beim `__exit__`. Das blockierende Verhalten hängt von `mg.is_interacitve()` ab (und folgt dem Verhalten von `mg.show` oder kann explizit über das Schlüsselwortargument block gesteuert werden).
Auswahl des GUI-Toolkits#
mpl_gui verwendet Matplotlib-Backends für die tatsächliche Bereitstellung der GUI-Bindings. Analog zu matplotlib.use und matplotlib.pyplot.switch_backend bietet mpl_gui mpl_gui.select_gui_toolkit zur Auswahl des verwendeten GUI-Toolkits. select_gui_toolkit hat dasselbe Fallback-Verhalten wie pyplot und speichert seinen Zustand in rcParams["backend"]. mpl_gui wird konsistent mit von matplotlib.pyplot verwalteten Figures im selben Prozess koexistieren.