Skip to content

Decide how to support qt6/gtk4 #19226

Closed
Closed

Description

@anntzer

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

  1. jklymak commented on Jan 3, 2021

    @jklymak
    Member

    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 ;-).

  2. anntzer commented on Jan 3, 2021

    @anntzer
    ContributorAuthor

    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...

  3. QuLogic commented on Jan 4, 2021

    @QuLogic
    Member

    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?

  4. anntzer commented on Jan 5, 2021

    @anntzer
    ContributorAuthor

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

  5. anntzer commented on Jan 11, 2021

    @anntzer
    ContributorAuthor

    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?

  6. milos-korenciak commented on Feb 1, 2021

    @milos-korenciak

    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.))

  7. jklymak commented on Feb 1, 2021

    @jklymak
    Member

    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?

  8. QuLogic commented on Feb 1, 2021

    @QuLogic
    Member

    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.

  9. anntzer commented on Feb 8, 2022

    @anntzer
    ContributorAuthor

    Done.

  10. added this to the v3.5.0 milestone on Feb 8, 2022
  11. YihaoJW commented on Aug 30, 2023

    @YihaoJW

    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

  12. QuLogic commented on Aug 30, 2023

    @QuLogic
    Member

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

  13. YihaoJW commented on Aug 31, 2023

    @YihaoJW

    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']

  14. QuLogic commented on Aug 31, 2023

    @QuLogic
    Member

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions