Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ac43f88

Browse files
committed
Document what pyplot expects from a backend.
1 parent c5ed8eb commit ac43f88

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

doc/users/explain/backends.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,6 @@ More generally, any importable backend can be selected by using any of the
237237
methods above. If ``name.of.the.backend`` is the module containing the
238238
backend, use ``module://name.of.the.backend`` as the backend name, e.g.
239239
``matplotlib.use('module://name.of.the.backend')``.
240+
241+
Information for backend implementers is available at
242+
:doc:`/users/explain/writing_a_backend_pyplot_interface`.

doc/users/explain/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Explanations
1010

1111
api_interfaces.rst
1212
backends.rst
13+
writing_a_backend_pyplot_interface.rst
1314
interactive.rst
1415
fonts.rst
1516
event_handling.rst
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
=========================================
2+
Writing a backend -- the pyplot interface
3+
=========================================
4+
5+
This page assumes general understanding of the information in the
6+
:doc:`/users/explain/backends` page, and is instead intended as reference for
7+
third-party backend implementers. It also only deals with the interaction
8+
between backends and `.pyplot`, not with the rendering side, which is described
9+
in `.backend_template`.
10+
11+
There are two APIs for defining backends: a new canvas-based API (introduced in
12+
Matplotlib 3.6), and an older function-based API. The new API is simpler to
13+
implement because many methods can be inherited from "parent backends". It is
14+
recommended if back-compatibility for Matplotlib < 3.6 is not a concern.
15+
However, the old API remains supported.
16+
17+
Fundamentally, a backend module needs to provide information to `.pyplot`, so
18+
that
19+
20+
1. `.pyplot.figure()` can create a new `.Figure` instance and associate it with
21+
an instance of a backend-provided canvas class, itself hosted in an instance
22+
of a backend-provided manager class.
23+
2. `.pyplot.show()` can show all figures and start the GUI event loop (if any).
24+
25+
To do so, the backend module must define a ``backend_module.FigureCanvas``
26+
subclass of `.FigureCanvasBase`. In the canvas-based API, this is the only
27+
strict requirement for backend modules. The function-based API additionally
28+
requires many module-level functions to be defined.
29+
30+
Canvas-based API (Matplotlib >= 3.6)
31+
------------------------------------
32+
33+
1. **Creating a figure**: `.pyplot.figure()` calls
34+
``figure = Figure(); FigureCanvas.new_manager(figure, num)``
35+
(``new_manager`` is a classmethod) to instantiate a canvas and a manager and
36+
set up the ``figure.canvas`` and ``figure.canvas.manager`` attributes.
37+
Figure unpickling uses the same approach, but replaces the newly
38+
instantiated ``Figure()`` by the unpickled figure.
39+
40+
Interactive backends should customize the effect of ``new_manager`` by
41+
setting the ``FigureCanvas.manager_class`` attribute to the desired manager
42+
class, and additionally (if the canvas cannot be created before the manager,
43+
as in the case of the wx backends) by overriding the
44+
``FigureManager.create_with_canvas`` classmethod. (Non-interactive backends
45+
can normally use a trivial ``FigureManagerBase`` and can therefore skip this
46+
step.)
47+
48+
After a new figure is registered with `.pyplot` (either via
49+
`.pyplot.figure()` or via unpickling), if in interactive mode, `.pyplot`
50+
will call its canvas' ``draw_idle()`` method, which can be overridden as
51+
desired.
52+
53+
2. **Showing figures**: `.pyplot.show()` calls
54+
``FigureCanvas.manager_class.pyplot_show()`` (a classmethod), forwarding any
55+
arguments, to start the main event loop.
56+
57+
By default, ``pyplot_show()`` checks whether there are any ``managers``
58+
registered with `.pyplot` (exiting early if not), calls ``manager.show()``
59+
on all such managers, and then, if called with ``block=True`` (or with
60+
the default ``block=None`` and out of IPython's pylab mode and not in
61+
interactive mode), calls ``FigureCanvas.manager_class.start_main_loop()``
62+
(a classmethod) to start the main event loop. Interactive backends should
63+
therefore override the ``FigureCanvas.manager_class.start_main_loop``
64+
classmethod accordingly (or alternatively, they may also directly override
65+
``FigureCanvas.manager_class.pyplot_show`` directly).
66+
67+
Function-based API
68+
------------------
69+
70+
1. **Creating a figure**: `.pyplot.figure()` calls
71+
``new_figure_manager(num, *args, **kwargs)`` (which also takes care of
72+
creating the new figure as ``Figure(*args, **kwargs)``); unpickling calls
73+
``new_figure_manager_given_figure(num, figure)``.
74+
75+
Furthermore, in interactive mode, the first draw of the newly registered
76+
figure can be customized by providing a module-level
77+
``draw_if_interactive()`` function. (In the new canvas-based API, this
78+
function is not taken into account anymore.)
79+
80+
2. **Showing figures**: `.pyplot.show()` calls a module-level ``show()``
81+
function, which is typically generated via the ``ShowBase`` class and its
82+
``mainloop`` method.

0 commit comments

Comments
 (0)