From 5aaef574db41d6faaf4409553c10509884b62bd9 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 19 Mar 2025 00:02:53 +0100 Subject: [PATCH 1/2] DOC: Improve interactive figures guide / Blocking input Side-topic spinning of from #29742. - Move the paragraph on "GUI events" to it's own section and before "Event loops". It's related but not directly needed for the event loop discussion. It was an odd side topic in the old location between "Event loops" and "Command prompt integration". - Rephrase the section on "Blocking the prompt" and some other smaller wording improvements Note: There will be a follow-up on #29742, but I think it's best to keep these unrelated changes separate and get them out of the way before reworking #29742. --- .../figure/interactive_guide.rst | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/galleries/users_explain/figure/interactive_guide.rst b/galleries/users_explain/figure/interactive_guide.rst index 0a6e9916bc9d..a7a41cec443c 100644 --- a/galleries/users_explain/figure/interactive_guide.rst +++ b/galleries/users_explain/figure/interactive_guide.rst @@ -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. @@ -23,6 +23,21 @@ handling system `, `Interactive Tutorial `Interactive Applications using Matplotlib `__. + +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 +` encapsulate the details of the GUI frameworks and +provide a framework-independent interface to GUI events through Matplotlib's +:ref:`event handling system `. 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 =========== @@ -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 -` for each GUI toolkit we support which uses the -toolkit API to bridge the toolkit UI events into Matplotlib's :ref:`event -handling system `. 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 @@ -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 + 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: @@ -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 th 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 From 7ae6260ac1830a34f6c04bb698a0fa975fbb0963 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:59:21 +0200 Subject: [PATCH 2/2] Update galleries/users_explain/figure/interactive_guide.rst Co-authored-by: Elliott Sales de Andrade --- galleries/users_explain/figure/interactive_guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/galleries/users_explain/figure/interactive_guide.rst b/galleries/users_explain/figure/interactive_guide.rst index a7a41cec443c..21658bb5849b 100644 --- a/galleries/users_explain/figure/interactive_guide.rst +++ b/galleries/users_explain/figure/interactive_guide.rst @@ -113,8 +113,8 @@ Blocking the prompt 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 th CLI event loop because the Python +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