Repository navigation
Description
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?
Activity
jklymak commentedon 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 commentedon 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 commentedon 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 commentedon Jan 5, 2021
I guess we just need to wait for a pygobject release with gtk4 support to know...
anntzer commentedon 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 commentedon 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.))
jklymak commentedon Feb 1, 2021
Perhaps you could try #19255?
QuLogic commentedon Feb 1, 2021
I think you might want to try #19334.
anntzer commentedon Feb 8, 2022
Done.
YihaoJW commentedon 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 commentedon Aug 30, 2023
Both Qt6 and Qt5 are supported by
QtAgg;Qt5Aggis a deprecated alias that only supports Qt5.YihaoJW commentedon Aug 31, 2023
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 commentedon Aug 31, 2023
Yes, it appears that the error is not coming from Matplotlib, but this
pydev_ipythonhook.