mpl-gui 文件#

動機#

此專案是 Matplotlib 在 pyplot 中提供的 GUI 事件迴圈管理工具的改版原型空間。

pyplot 模組目前提供兩個關鍵但無關的功能

  1. 提供一個受 MATLAB 啟發/模仿的具狀態的隱含 API

  2. 提供 Matplotlib 與 GUI 事件迴圈之間的互動管理,包括保持圖表的存活

雖然在提示符號下工作時可能非常方便,但具狀態的 API 可能導致脆弱的程式碼,這些程式碼以令人困惑的方式依賴於全域狀態,尤其是在程式庫程式碼中使用時。另一方面,matplotlib.pyplot 在對使用者隱藏他們正在開發 GUI 應用程式的事實方面做得非常好,並與 IPython 一起處理許多與並行執行 GUI 應用程式相關的細節。

範例#

如果您想確定此程式碼沒有秘密依賴 pyplot,請執行

import sys
sys.modules['matplotlib.pyplot'] = None

這將阻止 pyplot 被匯入!

顯示#

API 的核心是 show

import mpl_gui as mg
from matplotlib.figure import Figure

fig1 = Figure(label='A Label!')

fig2 = Figure()

mg.show([fig1, fig2])

它將顯示圖表並阻塞直到它們關閉。作為「顯示」過程的一部分,將建立正確的 GUI 物件、將其放在螢幕上,並執行主機 GUI 框架的事件迴圈。

阻塞(或不阻塞)#

plt.ionplt.ioff 類似,我們提供 mg.ion()mg.ioff(),它們具有相同的語意。因此

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!

plt.show 相同,您可以透過 block 關鍵字引數明確控制 mg.show 的阻塞行為

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

互動式狀態是 Matplotlib 共用的,也可以使用 matplotlib.interactive 控制,並透過 matplotlib.is_interactive 查詢。

圖表和軸建立#

matplotlib.pyplot 類似,我們也提供 figuresubplotssubplot_mosaic

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])

如果 mpl_gui 處於「互動模式」,則 mpl_gui.figurempl_gui.subplotsmpl_gui.subplot_mosaic 將自動將新的圖表放在螢幕上的視窗中(但不執行事件迴圈)。

FigureRegistry#

在上面的範例中,使用者有責任追蹤所建立的 Figure 實例。如果使用者沒有保持對 fig 物件的硬引用,無論是直接地還是透過其子物件間接地,那麼它將像任何其他 Python 物件一樣被垃圾回收。雖然這在某些情況下可能有利(例如,建立許多臨時圖表的腳本或函式)。它失去了 matplotlib.pyplot 為您追蹤實例的便利性。為此,我們也提供了 FigureRegistry

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

因此,如果您僅使用此受限的 pyplot API 集,則可以變更

import matplotlib.pyplot as plt

import mpl_gui as mg
plt = mg.FigureRegistry()

並具有(大部分)可直接替換的元件。

此外,還有一個 FigureRegistry.by_label 配件,它會傳回一個將圖表的標籤對應到每個圖表的字典

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#

一個非常常見的用例是建立多個圖表,然後在最後一起顯示它們。為了方便起見,我們提供了 FigureRegistry 的子類別,該子類別可以用作內容管理器,它(在本地)追蹤已建立的圖表並在退出時顯示它們

import mpl_gui as mg

with mg.FigureContext() as fc:
    fc.subplot_mosaic('AA\nBC')
    fc.figure()
    fc.subplots(2, 2)

這將建立 3 個圖表,並在 __exit__ 上阻塞。阻塞行為取決於 mg.is_interacitve() (並遵循 mg.show 的行為或可以透過 block 關鍵字引數明確控制)。

選擇 GUI 工具組#

mpl_gui 利用 Matplotlib 後端 來實際提供 GUI 繫結。與 matplotlib.usematplotlib.pyplot.switch_backend 類似,mpl_gui 提供 mpl_gui.select_gui_toolkit 來選擇使用哪個 GUI 工具組。select_gui_toolkitpyplot 具有相同的回退行為,並將其狀態儲存在 rcParams["backend"] 中。mpl_gui 將在同一個過程中與 matplotlib.pyplot 管理的圖表一致地共存。