|
| 1 | +Figures can be attached to and removed from pyplot |
| 2 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 3 | +Figures can now be attached to and removed from management through pyplot, which in |
| 4 | +the background also means a less strict coupling to backends. |
| 5 | + |
| 6 | +In particular, standalone figures (created with the `.Figure` constructor) can now be |
| 7 | +registered with the `.pyplot` module by calling ``plt.figure(fig)``. This allows to |
| 8 | +show them with ``plt.show()`` as you would do with any figure created with pyplot |
| 9 | +factory methods such as ``plt.figure()`` or ``plt.subplots()``. |
| 10 | + |
| 11 | +When closing a shown figure window, the related figure is reset to the standalone |
| 12 | +state, i.e. it's not visible to pyplot anymore, but if you still hold a reference |
| 13 | +to it, you can continue to work with it (e.g. do ``fig.savefig()``, or re-add it |
| 14 | +to pyplot with ``plt.figure(fig)`` and then show it again). |
| 15 | + |
| 16 | +The following is now possible - though the example is exaggerated to show what's |
| 17 | +possible. In practice, you'll stick with much simpler versions for better |
| 18 | +consistency :: |
| 19 | + |
| 20 | + import matplotlib.pyplot as plt |
| 21 | + from matplotlib.figure import Figure |
| 22 | + |
| 23 | + # Create a standalone figure |
| 24 | + fig = Figure() |
| 25 | + ax = fig.add_subplot() |
| 26 | + ax.plot([1, 2, 3], [4, 5, 6]) |
| 27 | + |
| 28 | + # Register it with pyplot |
| 29 | + plt.figure(fig) |
| 30 | + |
| 31 | + # Modify the figure through pyplot |
| 32 | + plt.xlabel("x label") |
| 33 | + |
| 34 | + # Show the figure |
| 35 | + plt.show() |
| 36 | + |
| 37 | + # Close the figure window through the GUI |
| 38 | + |
| 39 | + # Continue to work on the figure |
| 40 | + fig.savefig("my_figure.png") |
| 41 | + ax.set_ylabel("y label") |
| 42 | + |
| 43 | + # Re-register the figure and show it again |
| 44 | + plt.figure(fig) |
| 45 | + plt.show() |
| 46 | + |
| 47 | +Technical detail: Standalone figures use `.FigureCanvasBase` as canvas. This is |
| 48 | +replaced by a backend-dependent subclass when registering with pyplot, and is |
| 49 | +reset to `.FigureCanvasBase` when the figure is closed. `.Figure.savefig` uses |
| 50 | +the current canvas to save the figure (if possible). Since `.FigureCanvasBase` |
| 51 | +can not render the figure, when saving the figure, it will fallback to a suitable |
| 52 | +canvas subclass, e.g. `.FigureCanvasAgg` for raster outputs such as png. |
| 53 | +Any Agg-based backend will create the same file output. However, there may be |
| 54 | +slight differences for non-Agg backends; e.g. if you use "GTK4Cairo" as |
| 55 | +interactive backend, ``fig.savefig("file.png")`` may create a slightly different |
| 56 | +image depending on whether the figure is registered with pyplot or not. In |
| 57 | +general, you should not store a reference to the canvas, but rather always |
| 58 | +obtain it from the figure with ``fig.canvas``. This will return the current |
| 59 | +canvas, which is either the original `.FigureCanvasBase` or a backend-dependent |
| 60 | +subclass, depending on whether the figure is registered with pyplot or not. |
| 61 | +Additionally, the swapping of the canvas currently does not play well with |
| 62 | +blitting of matplotlib widgets; in such cases either deactivate blitting or do not |
| 63 | +continue to use the figure (e.g. saving it after closing the window). |
0 commit comments