FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[ENH]: Ctrl+C on a blocking show() should close the figure window · Issue #23385 · matplotlib/matplotlib · GitHub

Repository navigation

[ENH]: Ctrl+C on a blocking show() should close the figure window #23385

Open

Description

Problem

Currently, Ctrl+C terminates the show() call, but the window stays visible.

Proposed solution

No response

Activity

  1. QuLogic commented on Jul 4, 2022

    Member

    It should already do that. If you're seeing alternate behaviour, that's backend specific, so you should specify.

  2. timhoffm commented on Jul 5, 2022

    MemberAuthor

    Observed in IPython + Qt

  3. QuLogic commented on Jul 5, 2022

    Member

    On main or in a release? Qt was implemented in #13306.

  4. daniilS commented on Jul 5, 2022

    Contributor

    The figure window stays open in REPL with the tkinter backend too

  5. timhoffm commented on Jul 6, 2022

    MemberAuthor

    Tested on main + ipython +

    • qtagg: Ctrl+C ends the blocking show() call via a KeyboardInterrupt, but the figure window stays alive
    • tkagg: same as qtagg
    • wxagg: Ctrl+C does not end the blocking show() call
  6. timhoffm commented on Oct 11, 2023

    MemberAuthor

    Note on tkagg: I've tried to add

    except KeyboardInterrupt:
        first_manager.window.destroy()
    

    at

    try:
    first_manager.window.mainloop()
    finally:
    manager_class._owns_mainloop = False

    and that indeed closes the window. But when trying to show the next figure, I get a stack trace

    ---------------------------------------------------------------------------
    TclError                                  Traceback (most recent call last)
    Cell In[5], line 1
    ----> 1 plt.show()
    
    File ~/git/matplotlib/lib/matplotlib/pyplot.py:526, in show(*args, **kwargs)
        482 """
        483 Display all open figures.
        484 
       (...)
        523 explicitly there.
        524 """
        525 _warn_if_gui_out_of_main_thread()
    --> 526 return _get_backend_mod().show(*args, **kwargs)
    
    File ~/git/matplotlib/lib/matplotlib/backend_bases.py:3398, in _Backend.show(cls, block)
       3396 for manager in managers:
       3397     try:
    -> 3398         manager.show()  # Emits a warning for non-interactive backend.
       3399     except NonGuiException as exc:
       3400         _api.warn_external(str(exc))
    
    File ~/git/matplotlib/lib/matplotlib/backends/_backend_tk.py:561, in FigureManagerTk.show(self)
        559     self.canvas.draw_idle()
        560 if mpl.rcParams['figure.raise_window']:
    --> 561     self.canvas.manager.window.attributes('-topmost', 1)
        562     self.canvas.manager.window.attributes('-topmost', 0)
        563 self._shown = True
    
    File ~/anaconda3/envs/mpl-dev/lib/python3.11/tkinter/__init__.py:2032, in Wm.wm_attributes(self, *args)
       2014 """This subcommand returns or sets platform specific attributes
       2015 
       2016 The first form returns a list of the platform specific flags and
       (...)
       2029 On Unix, there are currently no special attribute values.
       2030 """
       2031 args = ('wm', 'attributes', self._w) + args
    -> 2032 return self.tk.call(args)
    
    TclError: can't invoke "wm" command: application has been destroye
    

    It seems that Tk is not creating a new application for every plot. But I'm too little of a Tk expert to find out how to do this properly. Ping @daniilS do you know how to handle this?

  7. daniilS commented on Oct 12, 2023

    Contributor

    I think the issue is that just calling first_manager.window.destroy() leaves the manager with a stale reference to the window. Replacing it with Gcf.destroy(first_manager) (which is called when the window is manually closed, see below) should work.

    def destroy(*args):
    Gcf.destroy(self)
    self.window.protocol("WM_DELETE_WINDOW", destroy)

  8. tacaswell commented on Oct 17, 2023

    Member

    We should try to avoid injecting Gcf into the backend modules if we can and should not assume that the window is managed by pyplot/Gcf.

    matplotlib/mpl-gui#8 is an idea we probably have to implement in Matplotlib core (independent of what we do with mpl-gui) in that we need to add the ability to Figure (or CanvasBase) to inject a cleanup callback at initialization time the same way with Artist we inject a remove callback when we add it to the parent (which is also the source of one of our (many) circular references but that is neither here nor there).

  9. anntzer commented on Nov 4, 2023

    Contributor

    @timhoffm re:

    qtagg: Ctrl+C ends the blocking show() call via a KeyboardInterrupt, but the figure window stays alive

    Were you testing with qt5 or qt6? I just noted https://doc.qt.io/qt-6/qtcore-changes-qt6.html#other-classes:

    In Qt 5, QCoreApplication::quit() was equivalent to calling QCoreApplication::exit(). This just exited the main event loop.
    In Qt 6, the method will instead try to close all top-level windows by posting a close event. The windows are free to cancel the shutdown process by ignoring the event.
    Call QCoreApplication::exit() to keep the non-conditional behavior.

    Perhaps(?) we may be able to simplify #27064 by just always calling exit() instead of quit()? (both also exist for QEventLoop)

  10. timhoffm commented on Nov 5, 2023

    MemberAuthor

    I don't remember which Qt version I tested with. But as I read this, quit and exit are equivalent for Qt 5 and don't close windows there. So as long as we support Qt5, we still need to handle window closing ourselves. Furthermore in Qt6 quit() was changed to close the windows. So I suppose the Qt6-only simplification would be to drop window closing, but continue to use quit()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL