Skip to content
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

Differences with show() between backends #1

Open
greglucas opened this issue Dec 3, 2021 · 4 comments
Open

Differences with show() between backends #1

greglucas opened this issue Dec 3, 2021 · 4 comments

Comments

@greglucas
Copy link
Collaborator

I was just testing out the examples from the docs and figured I would put some quick findings here while running on a Mac.

  • Documentation: Change subplot_module to subplot_mosaic in a couple of places in the code samples
  • qt5agg: mg.show() does not exit after closing both figures, the event loop keeps running
  • macosx: mg.show() closing one figure closes all of the figures, as if the closeWindow gets sent to every figure, not just the one clicked.
  • tkagg: In the second fr.show() call in the examples I get this error: _tkinter.TclError: can't invoke "wm" command: application has been destroyed (macosx seems to get through this and the qt5agg I don't think ever even gets here due to the event loop not quiting after the first show() as mentioned above)
@tacaswell
Copy link
Member

I fixed the doc typos.

I suspect the issues with show are all due to the fact that mg.show is implemented by calling https://github.com/tacaswell/mpl-gui/blob/9825fe856b9cb5266e737a27ca8c16a8b848da5c/mpl_gui/__init__.py#L78-L83 on the first canvas we find rather that calling mainloop()

For Qt this is https://github.com/matplotlib/matplotlib/blob/a35921c407aced5e65d39b29fd942676ee03679b/lib/matplotlib/backends/backend_qt.py#L402-L412 vs https://github.com/matplotlib/matplotlib/blob/a35921c407aced5e65d39b29fd942676ee03679b/lib/matplotlib/backends/backend_qt.py#L1023-L1026

In main difference is in the start_event_loop case, we are starting from a canvas and are running an secondary QEventLoop object rather than the main qApp (not sure why yet, suspect there is a good reason for that). However, this means that the signal from the qApp that all of the windows have been closed is never emitted (which seems fair because we are not running its event loop).

The reason mpl-gui is not using mainloop is that start_event_loop takes a timeout on all backends but mainloop does not.

At least with Qt you can produce a version of this behavior with just Matplotlib via

import matplotlib.pyplot as plt

plt.figure()
plt.figure()
plt.pause(50)
# manually close the windows

After 50s you will get the prompt back.

The "simple" fix for now is to put is logic to try running mainloop if there is no timeout, and start_event_loop otherwise, but I think the better fix is to add a timeout to mainloop but that needs lots of changes upstream.

@tacaswell
Copy link
Member

Having show block with no timeout on tk is currently broken because the mpl tk backend relies on grabbing the first manager from Gcf to sort out how to start the tk main loop. Will have to think about this a bit, may not be able to get away with just re-using the upstream backends and have some toolkit dependent code in this repo :/

@tacaswell
Copy link
Member

I think I have this working consistently from {qt5, qt6, gtk3, gtk4, tk}. I do not have easy access to a mac with a dev environment set up and could not get wx to install easily.

These is now a UAT.py at the top level which prints explaining what you should see.

@greglucas
Copy link
Collaborator Author

First pop-up: Figure 1 is printed instead of Figure 0, in all backends I believe, so maybe just a typo?

macosx: UAT.py works the same as the other backends!

wxagg: I also have issues with wx. If you have miniconda you should be able to get the binary pythonw prompt, which is what I've been using for testing. Here is my traceback running pythonw UAT.py wxagg

Traceback (most recent call last):
  File "mpl-gui/UAT.py", line 52, in <module>
    mg.show([fig1, fig2])
  File "mpl-gui/mpl_gui/__init__.py", line 71, in show
    managers.append(promote_figure(fig))
  File "mpl-gui/mpl_gui/_promotion.py", line 60, in promote_figure
    manager = _backend_mod.new_figure_manager_given_figure(next(_figure_count), fig)
  File "matplotlib/lib/matplotlib/backends/backend_wx.py", line 1373, in new_figure_manager_given_figure
    frame = FigureFrameWx(num, figure, canvas_class=cls.FigureCanvas)
  File "matplotlib/lib/matplotlib/backends/backend_wx.py", line 886, in __init__
    super().__init__(parent=None, id=-1, pos=pos)
wx._core.PyNoAppError: The wx.App object must be created first!

One more general thing unrelated to mpl-gui would be that I found tk to do a nice tiling of the windows so I knew I had 3 separate figures. But, the others put windows exactly underneath one another and it looks like you only have one figure open even though there may be some buried. I haven't looked to see if there are issues tracking this in MPL yet, so perhaps others have already written that up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants