8000 Document what pyplot expects from a backend. · matplotlib/matplotlib@0986e93 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0986e93

Browse files
committed
Document what pyplot expects from a backend.
1 parent 7e589f6 commit 0986e93

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

doc/users/explain/backends.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,6 @@ More generally, any importable backend can be selected by using any of the
252252
methods above. If ``name.of.the.backend`` is the module containing the
253253
backend, use ``module://name.of.the.backend`` as the backend name, e.g.
254254
``matplotlib.use('module://name.of.the.backend')``.
255+
256+
Information for backend implementers is available at
257+
:doc:`/users/explain/writing_a_backend`.

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

0 commit comments

Comments
 (0)
0