编写后端 —— pyplot 接口#
本页面假设您已大致理解“后端”页面中的信息,而是旨在为第三方后端实现者提供参考。它也仅涉及后端与 pyplot
之间的交互,而不涉及渲染方面,渲染方面在 backend_template
中描述。
定义后端有两种 API:新的基于画布的 API(Matplotlib 3.6 中引入),以及旧的基于函数的 API。新的 API 更易于实现,因为许多方法可以从“父后端”继承。如果不需要兼容 Matplotlib < 3.6,则推荐使用此 API。然而,旧的 API 仍受支持。
基本上,后端模块需要向 pyplot
提供信息,以便
pyplot.figure()
可以创建一个新的Figure
实例,并将其与后端提供的画布类的实例关联起来,该画布类实例本身托管在后端提供的管理器类的实例中。pyplot.show()
可以显示所有图形并启动 GUI 事件循环(如果有)。
为此,后端模块必须定义一个 backend_module.FigureCanvas
,它是 FigureCanvasBase
的子类。在基于画布的 API 中,这是后端模块的唯一严格要求。基于函数的 API 还需要定义许多模块级别的函数。
基于画布的 API (Matplotlib >= 3.6)#
创建图形:
pyplot.figure()
调用figure = Figure(); FigureCanvas.new_manager(figure, num)
(new_manager
是一个类方法),以实例化一个画布和一个管理器,并设置figure.canvas
和figure.canvas.manager
属性。图形反序列化(unpickling)使用相同的方法,但将新实例化的Figure()
替换为反序列化的图形。交互式后端应通过将
FigureCanvas.manager_class
属性设置为所需的管理器类来定制new_manager
的效果,此外(如果画布不能在管理器之前创建,如 wx 后端的情况)通过重写FigureManager.create_with_canvas
类方法。(非交互式后端通常可以使用简单的FigureManagerBase
,因此可以跳过此步骤。)当一个新的图形注册到
pyplot
后(通过pyplot.figure()
或通过反序列化),如果处于交互模式,pyplot
将调用其画布的draw_idle()
方法,该方法可以根据需要进行重写。显示图形:
pyplot.show()
调用FigureCanvas.manager_class.pyplot_show()
(一个类方法),转发所有参数,以启动主事件循环。默认情况下,
pyplot_show()
会检查是否有任何managers
注册到pyplot
(如果没有则提前退出),对所有此类管理器调用manager.show()
,然后,如果使用block=True
调用(或使用默认的block=None
并且不在 IPython 的 pylab 模式下且不是交互模式),则调用FigureCanvas.manager_class.start_main_loop()
(一个类方法)以启动主事件循环。因此,交互式后端应相应地重写FigureCanvas.manager_class.start_main_loop
类方法(或者,它们也可以直接重写FigureCanvas.manager_class.pyplot_show
)。
基于函数的 API#
创建图形:
pyplot.figure()
调用new_figure_manager(num, *args, **kwargs)
(它也负责将新图形创建为Figure(*args, **kwargs)
);反序列化(unpickling)调用new_figure_manager_given_figure(num, figure)
。此外,在交互模式下,可以通过提供模块级别的
draw_if_interactive()
函数来定制新注册图形的首次绘制。(在新的基于画布的 API 中,此函数不再考虑在内。)显示图形:
pyplot.show()
调用模块级别的show()
函数,该函数通常通过ShowBase
类及其mainloop
方法生成。
注册后端#
新后端要通过 matplotlib.use()
或 IPython 的 %matplotlib
魔术命令使用,它必须与 BackendRegistry
支持的三种方式之一兼容:
内置#
内置于 Matplotlib 的后端必须在 BackendRegistry
中硬编码其名称和 FigureCanvas.required_interactive_framework
。如果后端模块不是 f"matplotlib.backends.backend_{backend_name.lower()}"
,则 BackendRegistry._name_to_module
中也必须有一个条目。
module:// 语法#
任何独立模块中的后端(未内置于 Matplotlib 中)都可以通过指定模块路径的形式 module://some.backend.module
来使用。例如,mplcairo 使用 module://mplcairo.qt
。后端的交互式框架将取自其 FigureCanvas.required_interactive_framework
。
入口点#
外部后端模块可以在其 pyproject.toml
中使用 entry point
(入口点)来将自己注册为后端,例如 matplotlib-inline
所使用的。
[project.entry-points."matplotlib.backend"]
inline = "matplotlib_inline.backend_inline"
后端的交互式框架将取自其 FigureCanvas.required_interactive_framework
。所有入口点会一起加载,但仅在首次需要时(例如当后端名称未被识别为内置后端时,或首次调用 list_all()
时)才加载。