编写后端 -- pyplot 接口#

此页面假定对后端页面中的信息有基本的了解,而是作为第三方后端实现者的参考。它还只处理后端与pyplot之间的交互,而不是渲染方面,渲染方面在backend_template中描述。

有两种 API 用于定义后端:一种是新的基于画布的 API(在 Matplotlib 3.6 中引入),另一种是较旧的基于函数的 API。新的 API 更易于实现,因为许多方法可以从“父后端”继承。如果不需要与 Matplotlib < 3.6 的向后兼容性,则建议使用它。但是,仍然支持旧的 API。

从根本上讲,后端模块需要向pyplot提供信息,以便

  1. pyplot.figure()可以创建一个新的Figure实例,并将其与后端提供的画布类的实例关联起来,该实例本身托管在后端提供的管理器类的实例中。

  2. pyplot.show()可以显示所有图形并启动 GUI 事件循环(如果有)。

为此,后端模块必须定义backend_module.FigureCanvas作为FigureCanvasBase的子类。在基于画布的 API 中,这是后端模块的唯一严格要求。基于函数的 API 还需要定义许多模块级函数。

基于画布的 API (Matplotlib >= 3.6)#

  1. 创建图形pyplot.figure()调用figure = Figure(); FigureCanvas.new_manager(figure, num)new_manager是一个类方法)来实例化画布和管理器,并设置figure.canvasfigure.canvas.manager属性。图形取消腌制使用相同的方法,但是将新实例化的Figure()替换为取消腌制的图形。

    交互式后端应通过将FigureCanvas.manager_class属性设置为所需的管理器类来自定义new_manager的效果,并且(如果画布不能在管理器之前创建,就像 wx 后端的情况一样)通过覆盖FigureManager.create_with_canvas类方法。(非交互式后端通常可以使用一个简单的FigureManagerBase,因此可以跳过此步骤。)

    在通过pyplot.figure()或通过取消腌制将新图形注册到pyplot之后,如果在交互模式下,pyplot将调用其画布的draw_idle()方法,可以根据需要覆盖该方法。

  2. 显示图形pyplot.show()调用FigureCanvas.manager_class.pyplot_show()(类方法),转发任何参数,以启动主事件循环。

    默认情况下,pyplot_show()检查是否在pyplot中注册了任何managers(如果没有,则提前退出),对所有此类管理器调用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#

  1. 创建图形pyplot.figure()调用new_figure_manager(num, *args, **kwargs)(它还负责创建新图形,如Figure(*args, **kwargs));取消腌制调用new_figure_manager_given_figure(num, figure)

    此外,在交互模式下,可以通过提供模块级的draw_if_interactive()函数来自定义新注册图形的第一次绘制。(在新的基于画布的 API 中,不再考虑此函数。)

  2. 显示图形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:// 语法#

可以通过以module://some.backend.module的形式指定模块的路径来使用单独模块中的任何后端(未构建到 Matplotlib 中)。一个例子是mplcairomodule://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() 时。