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

Decide how to support qt6/gtk4 #19226

Closed
anntzer opened this issue Jan 3, 2021 · 13 comments
Closed

Decide how to support qt6/gtk4 #19226

anntzer opened this issue Jan 3, 2021 · 13 comments

Comments

@anntzer
Copy link
Contributor

anntzer commented Jan 3, 2021

Both qt6 and gtk4 have been recently released. qt6 already has a working python binding in pyside6; i guess both qt6 and a gtk4-supporting pygobject should be available "soon". (For qt6 I first raised the issue #16836 but that issue ended up being mostly about qt4.)

It turns out to be very easy to support pyside6 -- it's just a couple of import renames and certain things having moved out of the Qt namespace -- and I basically already have a patch for that. The main question, however, is whether we want to put that support in a "qt6agg" (and "qt6cairo") backend, or if we decide to move towards having a single "qtagg" (and "qtcairo") backend and fully move qt binding selection to 1) checking if anything is already imported in the process and 2) the QT_API environment variable.

Even as of today, if one selects the qt5agg backend but already has PyQt4 imported in the process, we'll silently switch to qt4agg for you (well, modulo the deprecation warning for qt4 support), so we already treat the two backends as somewhat interchangeable. Although I guess one of the reasons for doing so was that it was not possible to import both PyQt4 and PyQt5 into the same process at all (the second import would fail); I don't know if that's also going to be the case for qt6...

I'd say it makes sense to just have a single qtagg backend instead. The alternate solution of having both qt5agg and qt6agg would probably involve copy-pasting all of backend_qt5agg.py into backend_qt6agg.py, and then replacing backend_qt5agg.py by a small stub similar to the current backend_qt4agg.py, which is a bit... ugh.

The same question basically exists for gtk3/gtk4, although perhaps we can wait for a pygobject release that supports gtk4 to make sure it'll indeed make sense to go back to a single gtkagg. There we'd need to introduce a new GTK_API environment variable though? Also, there's the additional question of whether that'll confuse people using fairly old docs/versions and confusing that with the old gtkagg (=gtk2) backend, which was removed in matplotlib 2.0... (also, note that a non-numbered qtagg backend also existed back in the times of qt3(!) support (which was removed in matplotlib 1.3).)

TL;DR: 1) perhaps wait for PyQt6 and "pygobject4" before deciding on what to do with PySide6; 2) perhaps move to a single backend_qtagg and a single backend_gtkagg instead of splitting by version?

@jklymak
Copy link
Member

jklymak commented Jan 3, 2021

It would be great to just have one backend. But is there going to be call to use non compatible features of qt6? Is assume it is different in some ways ;-).

@anntzer
Copy link
Contributor Author

anntzer commented Jan 3, 2021

In practice, we just added a few checks in backend_qt5.py to support both qt4 and qt5 (you can grep for qVersion() >= '5.'); I don't expect qt5 and qt6 to be more different...

@QuLogic
Copy link
Member

QuLogic commented Jan 4, 2021

GTK4 is a major release bump for a reason; there are many many changes involved. However, I don't know how much of that will translate into Python due to duck typing in PyGObject.

How will this work out for embedding?

@anntzer
Copy link
Contributor Author

anntzer commented Jan 5, 2021

I guess we just need to wait for a pygobject release with gtk4 support to know...

@anntzer
Copy link
Contributor Author

anntzer commented Jan 11, 2021

Actually pygobject master basically works with gtk4; I gave a quick try at adapting backend_gtk3foo but it looks like it may require more fiddling than the qt5->qt6 transition which is quite mechanical (#19255). @QuLogic perhaps you may want to give it a try?

@milos-korenciak
Copy link

Please, could you just implement Qt6Agg for now? Because on BigSur (MacOS11.x) only PySide6 works correctly.
(It simply limits my team. (I know it is no argument.))

@jklymak
Copy link
Member

jklymak commented Feb 1, 2021

Please, could you just implement Qt6Agg for now? Because on BigSur (MacOS11.x) only PySide6 works correctly.

(It simply limits my team. (I know it is no argument.))

Perhaps you could try #19255?

@QuLogic
Copy link
Member

QuLogic commented Feb 1, 2021

Please, could you just implement Qt6Agg for now? Because on BigSur (MacOS11.x) only PySide6 works correctly.

I think you might want to try #19334.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 8, 2022

Done.

@anntzer anntzer added this to the v3.5.0 milestone Feb 8, 2022
@anntzer anntzer closed this as completed Feb 8, 2022
@YihaoJW
Copy link

YihaoJW commented Aug 30, 2023

matplotlib.use Still not recognize PyQt6 on macOS?
In the document, it only has PyQt5, since PyQt5 is not available Apple Silicon, seems need to use Qt6

interactive backends: GTK3Agg, GTK3Cairo, GTK4Agg, GTK4Cairo, MacOSX, nbAgg, QtAgg, QtCairo, TkAgg, TkCairo, WebAgg, WX, WXAgg, WXCairo, Qt5Agg, Qt5Cairo

@QuLogic
Copy link
Member

QuLogic commented Aug 30, 2023

Both Qt6 and Qt5 are supported by QtAgg; Qt5Agg is a deprecated alias that only supports Qt5.

@YihaoJW
Copy link

YihaoJW commented Aug 31, 2023

Both Qt6 and Qt5 are supported by QtAgg; Qt5Agg is a deprecated alias that only supports Qt5.

Thanks for the clarification, it seems DataSpell's patch caused this issue.

When I tried to use this QtAgg in Dataspell using the interactive shell. It got an error. But it does not get error directly running iPython in commend line.

Error when running in DataSpell shell

Python 3.9.18 (main, Aug 24 2023, 21:19:58)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.8.0 -- An enhanced Interactive Python. Type '?' for help.
PyDev console: using IPython 8.8.0
Python 3.9.18 (main, Aug 24 2023, 21:19:58)
[Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
import PyQt6
import matplotlib
matplotlib.use("QtAgg")
Traceback (most recent call last):
File "/path/to/venv/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3442, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "", line 1, in
matplotlib.use("QtAgg")
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/pydev_ipython/matplotlibtools.py", line 70, in patched_use
matplotlib.real_use(*args, **kwargs)
File "/path/to/venv/lib/python3.9/site-packages/matplotlib/init.py", line 1237, in use
plt.switch_backend(name)
File "/path/to/venv/lib/python3.9/site-packages/matplotlib/pyplot.py", line 356, in switch_backend
install_repl_displayhook()
File "/path/to/venv/lib/python3.9/site-packages/matplotlib/pyplot.py", line 157, in install_repl_displayhook
ip.enable_gui(ipython_gui_name)
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py", line 142, in enable_gui
return real_enable_gui(gui, app)
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/pydev_ipython/inputhook.py", line 536, in enable_gui
return gui_hook(app)
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/pydev_ipython/inputhook.py", line 174, in enable_qt
from pydev_ipython.qt_for_kernel import QT_API, QT_API_PYQT5
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 21, in do_import
module = self._system_import(name, *args, **kwargs)
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/pydev_ipython/qt_for_kernel.py", line 115, in
QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts)
File "/path/to/IDE/DataSpell.app/Contents/plugins/python-ce/helpers/pydev/pydev_ipython/qt_loaders.py", line 267, in load_qt
raise ImportError("""
ImportError:
Could not load requested Qt binding. Please ensure that
PyQt4 >= 4.7 or PySide >= 1.0.3 is available,
and only one is imported per session.
Currently-imported Qt library: None
PyQt4 installed: False
PyQt5 installed: False
PySide >= 1.0.3 installed: False
Tried to load: ['pyqtdefault', 'pyside', 'pyqt5']

@QuLogic
Copy link
Member

QuLogic commented Aug 31, 2023

Yes, it appears that the error is not coming from Matplotlib, but this pydev_ipython hook.

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

No branches or pull requests

5 participants