mpl-gui 文件#
動機#
此專案是一個原型空間,用於徹底檢修 Matplotlib 在 pyplot 中提供的 GUI 事件迴圈管理工具。
pyplot 模組目前提供兩個關鍵但無關的功能
提供一個有狀態的隱式 API,其節奏/靈感來自 MATLAB
提供 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.ion
和 plt.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
類似,我們還提供 figure
、subplots
和 subplot_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.figure
、mpl_gui.subplots
和 mpl_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.use
和 matplotlib.pyplot.switch_backend
,mpl_gui
提供 mpl_gui.select_gui_toolkit
來選擇使用的 GUI 工具組。 select_gui_toolkit
具有與 pyplot
相同的回退行為,並將其狀態儲存在 rcParams["backend"]
中。mpl_gui
將始終與在同一個進程中管理的 matplotlib.pyplot
圖表共存。