Figures can be attached to and removed from pyplot#
Figures can now be attached to and removed from management through pyplot, which in the background also means a less strict coupling to backends.
In particular, standalone figures (created with the Figure constructor) can now be
registered with the pyplot module by calling plt.figure(fig). This allows to
show them with plt.show() as you would do with any figure created with pyplot
factory methods such as plt.figure() or plt.subplots().
When closing a shown figure window, the related figure is reset to the standalone
state, i.e. it's not visible to pyplot anymore, but if you still hold a reference
to it, you can continue to work with it (e.g. do fig.savefig(), or re-add it
to pyplot with plt.figure(fig) and then show it again).
The following is now possible - though the example is exaggerated to show what's possible. In practice, you'll stick with much simpler versions for better consistency
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
# Create a standalone figure
fig = Figure()
ax = fig.add_subplot()
ax.plot([1, 2, 3], [4, 5, 6])
# Register it with pyplot
plt.figure(fig)
# Modify the figure through pyplot
plt.xlabel("x label")
# Show the figure
plt.show()
# Close the figure window through the GUI
# Continue to work on the figure
fig.savefig("my_figure.png")
ax.set_ylabel("y label")
# Re-register the figure and show it again
plt.figure(fig)
plt.show()
Technical detail: Standalone figures use FigureCanvasBase as canvas. This is
replaced by a backend-dependent subclass when registering with pyplot, and is
reset to FigureCanvasBase when the figure is closed. Figure.savefig uses
the current canvas to save the figure (if possible). Since FigureCanvasBase
can not render the figure, when saving the figure, it will fallback to a suitable
canvas subclass, e.g. FigureCanvasAgg for raster outputs such as png.
Any Agg-based backend will create the same file output. However, there may be
slight differences for non-Agg backends; e.g. if you use "GTK4Cairo" as
interactive backend, fig.savefig("file.png") may create a slightly different
image depending on whether the figure is registered with pyplot or not. In
general, you should not store a reference to the canvas, but rather always
obtain it from the figure with fig.canvas. This will return the current
canvas, which is either the original FigureCanvasBase or a backend-dependent
subclass, depending on whether the figure is registered with pyplot or not.
Additionally, the swapping of the canvas currently does not play well with
blitting of matplotlib widgets; in such cases either deactivate blitting or do not
continue to use the figure (e.g. saving it after closing the window).