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

Skip to content

DOC: Improve interactive figures guide / Blocking input #29773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 3, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 41 additions & 37 deletions galleries/users_explain/figure/interactive_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Interactive figures and asynchronous programming

Matplotlib supports rich interactive figures by embedding figures into
a GUI window. The basic interactions of panning and zooming in an
Axes to inspect your data is "baked in" to Matplotlib. This is
Axes to inspect your data is available out-of-the-box. This is
supported by a full mouse and keyboard event handling system that
you can use to build sophisticated interactive graphs.

Expand All @@ -23,6 +23,21 @@ handling system <event-handling>`, `Interactive Tutorial
`Interactive Applications using Matplotlib
<http://www.amazon.com/Interactive-Applications-using-Matplotlib-Benjamin/dp/1783988843>`__.


GUI events
==========

All GUI frameworks (Qt, Wx, Gtk, Tk, macOS, or web) have some method of
capturing user interactions and passing them back to the application, but
the exact details depend on the toolkit (for example callbacks in Tk or
the ``Signal`` / ``Slot`` framework in Qt). The Matplotlib :ref:`backends
<what-is-a-backend>` encapsulate the details of the GUI frameworks and
provide a framework-independent interface to GUI events through Matplotlib's
:ref:`event handling system <event-handling>`. By connecting functions
to the event handling system (see `.FigureCanvasBase.mpl_connect`), you can
interactively respond to user actions in a GUI toolkit agnostic way.


Event loops
===========

Expand Down Expand Up @@ -58,19 +73,6 @@ depending on the library, by methods with names like ``exec``,
``run``, or ``start``.


All GUI frameworks (Qt, Wx, Gtk, tk, macOS, or web) have some method of
capturing user interactions and passing them back to the application
(for example ``Signal`` / ``Slot`` framework in Qt) but the exact
details depend on the toolkit. Matplotlib has a :ref:`backend
<what-is-a-backend>` for each GUI toolkit we support which uses the
toolkit API to bridge the toolkit UI events into Matplotlib's :ref:`event
handling system <event-handling>`. You can then use
`.FigureCanvasBase.mpl_connect` to connect your function to
Matplotlib's event handling system. This allows you to directly
interact with your data and write GUI toolkit agnostic user
interfaces.


.. _cp_integration:

Command prompt integration
Expand All @@ -81,16 +83,16 @@ lets us interactively send code to the interpreter and get results
back. We also have the GUI toolkit that runs an event loop waiting
for user input and lets us register functions to be run when that
happens. However, if we want to do both we have a problem: the prompt
and the GUI event loop are both infinite loops that each think *they*
are in charge! In order for both the prompt and the GUI windows to be
and the GUI event loop are both infinite loops and cannot run in
parallel. In order for both the prompt and the GUI windows to be
responsive we need a method to allow the loops to "timeshare" :

1. let the GUI main loop block the python process when you want
interactive windows
2. let the CLI main loop block the python process and intermittently
run the GUI loop
3. fully embed python in the GUI (but this is basically writing a full
application)
1. **Blocking the prompt**: let the GUI main loop block the python
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: The bold phrases repeat the section titles that these variants are discussed in. This should make the connection more obvious.

process when you want interactive windows
2. **Input hook integration**: let the CLI main loop block the python
process and intermittently run the GUI loop
3. **Full embedding**: fully embed python in the GUI
(but this is basically writing a full application)

.. _cp_block_the_prompt:

Expand All @@ -108,24 +110,26 @@ Blocking the prompt
backend_bases.FigureCanvasBase.stop_event_loop


The simplest "integration" is to start the GUI event loop in
"blocking" mode and take over the CLI. While the GUI event loop is
running you cannot enter new commands into the prompt (your terminal
may echo the characters typed into the terminal, but they will not be
sent to the Python interpreter because it is busy running the GUI
event loop), but the figure windows will be responsive. Once the
event loop is stopped (leaving any still open figure windows
non-responsive) you will be able to use the prompt again. Re-starting
the event loop will make any open figure responsive again (and will
process any queued up user interaction).
The simplest solution is to start the GUI event loop and let it run
exclusively, which results in responsive figure windows. However, the
CLI event loop will not run, so that you cannot enter new commands.
We call this "blocking" mode. (Your terminal may echo the typed characters,
but they will not yet be processed by the CLI event loop because the Python
interpreter is busy running the GUI event loop).

It is possible to stop the GUI event loop and return control to the CLI
event loop. You can then use the prompt again, but any still open figure
windows are non-responsive. Re-starting the GUI event loop will make these
figure responsive again (and will process any queued up user interaction).


To start the event loop until all open figures are closed, use
`.pyplot.show` as ::
The typical command to show all figures and run the GUI event loop
exclusively until all figures are closed is ::

pyplot.show(block=True)
plt.show()

To start the event loop for a fixed amount of time (in seconds) use
`.pyplot.pause`.
Alternatively, you can start the GUI event loop for a fixed amount of time
using `.pyplot.pause`.

If you are not using `.pyplot` you can start and stop the event loops
via `.FigureCanvasBase.start_event_loop` and
Expand Down