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

Qt5 backend doesn't work with Qt 5.3 #3623

Closed
jenshnielsen opened this issue Oct 7, 2014 · 34 comments
Closed

Qt5 backend doesn't work with Qt 5.3 #3623

jenshnielsen opened this issue Oct 7, 2014 · 34 comments
Milestone

Comments

@jenshnielsen
Copy link
Member

I have previously had the Qt5 backend working with mpl 1.4.0 however It seems broken to me now.
Trying to do a simple plot with plt.plot results in

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-bf7ca2578bf6> in <module>()
----> 1 plt.plot(range(100))

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/pyplot.py in plot(*args, **kwargs)
   3089 @_autogen_docstring(Axes.plot)
   3090 def plot(*args, **kwargs):
-> 3091     ax = gca()
   3092     # allow callers to override the hold state by passing hold=True|False
   3093     washold = ax.ishold()

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/pyplot.py in gca(**kwargs)
    826     matplotlib.figure.Figure.gca : The figure's gca method.
    827     """
--> 828     ax =  gcf().gca(**kwargs)
    829     return ax
    830

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/pyplot.py in gcf()
    460         return figManager.canvas.figure
    461     else:
--> 462         return figure()
    463
    464 fignum_exists = _pylab_helpers.Gcf.has_fignum

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/pyplot.py in figure(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, **kwargs)
    433                                         frameon=frameon,
    434                                         FigureClass=FigureClass,
--> 435                                         **kwargs)
    436
    437         if figLabel:

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/backends/backend_qt5agg.py in new_figure_manager(num, *args, **kwargs)
     46     FigureClass = kwargs.pop('FigureClass', Figure)
     47     thisFig = FigureClass(*args, **kwargs)
---> 48     return new_figure_manager_given_figure(num, thisFig)
     49
     50

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/backends/backend_qt5agg.py in new_figure_manager_given_figure(num, figure)
     53     Create a new figure manager instance for the given figure.
     54     """
---> 55     canvas = FigureCanvasQTAgg(figure)
     56     return FigureManagerQT(canvas, num)
     57

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/backends/backend_qt5agg.py in __init__(self, figure)
    179         if DEBUG:
    180             print('FigureCanvasQtAgg: ', figure)
--> 181         FigureCanvasQT.__init__(self, figure)
    182         FigureCanvasAgg.__init__(self, figure)
    183         self._drawRect = None

/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib-1.5.x-py3.4-macosx-10.9-x86_64.egg/matplotlib/backends/backend_qt5.py in __init__(self, figure)
    235         # __init__() takes exactly 2 arguments (1 given) on QWidget
    236         # PyQt5
--> 237         super(FigureCanvasQT, self).__init__(figure=figure)
    238         self.figure = figure
    239         self.setMouseTracking(True)

TypeError: 'figure' is an unknown keyword argument

This is naturally because QtWidgets.QWidget does not take a figure keyword argument. Removing the kwarg seems to resolve the issue with a simple figure. But I am unsure if the intention of this line is to call init on QtWidgets.QWidget or FigureCanvasBase which does take that kwarg.

Since this has working before I guess that this is somehow related to me upgrading to Qt5.3.
The traceback above is from the master branch but the same seems to happen with 1.4.0

@jenshnielsen jenshnielsen added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Oct 7, 2014
@jenshnielsen jenshnielsen added this to the v1.4.1 milestone Oct 7, 2014
@jenshnielsen
Copy link
Member Author

The QT4 backend explicitly calls init on both of the parent classes:

# Note different super-calling style to backend_qt5
QtWidgets.QWidget.__init__(self)
FigureCanvasBase.__init__(self, figure)

@mfitzp can you remember why this difference exists between the Qt4 and Qt5 backends

@mfitzp
Copy link
Member

mfitzp commented Oct 8, 2014

@jenshnielsen If I remember correctly, the Qt5 backend uses super() because otherwise it wouldn't work. The init handling in PyQt5 was fixed so that super works as it should with QObject but the side effect seemed to be that it then didn't work by calling FigureCanvasBase.__init__() directly.

You're correct that the figure parameter is supposed to be going to FigureCanvasBase.

Can you give me some details of your system/setup so I can reproduce?

@jenshnielsen
Copy link
Member Author

This is on a Mac OSX 10.9 with Qt5.3.2, PyQt5 5.3.2 and python 3.4 from Homebrew as well.

I know that the backend used to work for me before so I am guessing that this is somehow related to me upgrading to QT5.3 but I haven't tried reinstalling Qt5.2

My understanding of super is that in this context it will call init() on the first class that is inherited from i.e. QtWidgets.QWidget but not on FigureCanvasBase.

@jenshnielsen
Copy link
Member Author

I can confirm that I see the issue that you describe when explicitly initialize the parent classes on Ubuntu 14.04 with Qt 5.2 ...

When explicitly calling QtWidgets.QWidget.init(self) it complains about missing figure. When calling QtWidgets.QWidget.init(self, figure=figure) it complains that figure is an unknown kwarg. I think there is a deeper issue here.

@stonebig
Copy link
Contributor

stonebig commented Oct 8, 2014

I was hoping Matplotlib 1.4.1 would be out "by October 1rst".
Has someone a new Forecast of release date ? (users are out in the cold with 1.4.0)

@tacaswell
Copy link
Member

@stonebig If you really need something that has been fixed on 1.4.x install from source. We have a couple of blocking issues left (take a look at the 1.4.1 milestone), an rc will be tagged once they are cleaned up. If you have spare cycles any help sorting those issues out would be appreciated.

@stonebig
Copy link
Contributor

stonebig commented Oct 9, 2014

hi @tacaswell ,

I'm relying on matplotlib versions (or releases candidates), as distributed by Christoph Gohlke, so it's a break for me to grab the latest source.
I could do what you suggest without blinking, IF Matplotlib was a pure python project, but github statistic states it is only a 87.3% python project.
(life is not as easy for python windows users as it is for linux ones)

@jenshnielsen
Copy link
Member Author

Ok, This actually doesn't have anything to do with qt 5.3

What happens is that I have the env variable QT_API set to pyqt

That results in pyqt4 being imported even within the qt5 backend which causes this issue.

@tacaswell tacaswell added not a blocker and removed Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. labels Oct 11, 2014
@tacaswell
Copy link
Member

re-labeled this as not-a-blocker as it seems to be a configuration issue.

@jenshnielsen
Copy link
Member Author

I would disagree on this being a config issue. It makes no sense for the matplotlib qt5 backend to be broken in a strange and hard to debug way just because I have set a variable to determine which qt4 library to use in the qt4 backend and in mayavi. The result of the current code is that matplotlib actually imports pyqt4 into the qt5 backend which imho is a clear bug.

@mfitzp
Copy link
Member

mfitzp commented Oct 12, 2014

The API switcher in qt_compat.py uses QT_API to determine which API to load (assuming it is set, otherwise it tries APIs in turn). If QT_API is set to a v4 API it is not possible to use PyQt5 as the backend. When implementing the support for PyQt5 I simply took the API selection code currently used for Qt4 and extended it not considering the effect where QT_API is used to determine the minor version of Qt4 rather than 4 vs. 5.

@jenshnielsen PR resolves this by checking the major version specified by the QT_API variable. However, if a v5 of the PySide API becomes available (don't know how likely this is) I think we'd be back in the same situation where it's impossible to specify a version of Qt4 API or Qt5 API independently.

Is adding a QT5_API environment variable a better solution? Or we could extend the QT_API to support multiple options e.g. QT_API=pyside,pyqt5. Thoughts? Either way the backend can then be chosen in matplotlib with the API used for it specified in the environment.

All this can be handled by logic in the qt_compat.py and would be transparent to the backends.

@tacaswell
Copy link
Member

Fair enough, I see what I was confused about now.

@jenshnielsen
Copy link
Member Author

I Agree with @mfitzp that this doesn't really work if/when a qt5 compatible version of pyside appears. I think that the simplest and best solution would be an additional env variable to specify which python qt5 implementation to use. But lets wait till we know if that is relevant.

@tacaswell
Copy link
Member

I suspect that this whole bit of logic should be re-written, but that is a bigger change than we want to make for 1.4.1.

@tacaswell
Copy link
Member

This is fixed by #3632 which has been merged.

@fccoelho
Copy link

fccoelho commented Jan 6, 2016

I am still having this issue: on pyqt5 5.4.2 and matplotlib 1.5.0
Can't even force matplotlib to use a different backend with

matplotlib.use('GTKAgg')

here is my error message:

File "/usr/local/lib/python3.4/dist-packages/matplotlib/backends/backend_qt5.py", line 239, in __init__
    super(FigureCanvasQT, self).__init__(figure=figure)
TypeError: 'figure' is an unknown keyword argument

@WeatherGod
Copy link
Member

Try the rc for v1.5.1, which should have this fix.

On Wed, Jan 6, 2016 at 12:32 PM, Flávio Codeço Coelho <
notifications@github.com> wrote:

I am still having this issue: on pyqt5 5.4.2 and matplotlib 1.5.0
Can't even force matplotlib to use a different backend with

matplotlib.use('GTKAgg')

here is my error message:

File "/usr/local/lib/python3.4/dist-packages/matplotlib/backends/backend_qt5.py", line 239, in init
super(FigureCanvasQT, self).init(figure=figure)TypeError: 'figure' is an unknown keyword argument


Reply to this email directly or view it on GitHub
#3623 (comment)
.

@tacaswell
Copy link
Member

Are you calling use before you import pyplot?

@fccoelho
Copy link

fccoelho commented Jan 6, 2016

Yes I am.

On Wed, Jan 6, 2016 at 3:37 PM, Thomas A Caswell notifications@github.com
wrote:

Are you calling use before you import pyplot?


Reply to this email directly or view it on GitHub
#3623 (comment)
.

Flávio Codeço Coelho

+55(21) 3799-5551
Professor
Escola de Matemática Aplicada
Fundação Getulio Vargas
Praia de Botafogo, 190 sala 312
Rio de Janeiro - RJ
22250-900
Brasil

@tacaswell
Copy link
Member

Can you provide a full example of how to trigger this?

import matplotlib
matplotlib.use('gtkagg')
import matplotlib.pyplot as plt

should never touch any of the Qt related files.

@fccoelho
Copy link

fccoelho commented Jan 6, 2016

This is what I have:

import matplotlib
matplotlib.use('GTKAgg', force=True)
from matplotlib import pyplot as P

On Wed, Jan 6, 2016 at 4:17 PM, Thomas A Caswell notifications@github.com
wrote:

Can you provide a full example of how to trigger this?

import matplotlib
matplotlib.use('gtkagg')import matplotlib.pyplot as plt

should never touch any of the Qt related files.


Reply to this email directly or view it on GitHub
#3623 (comment)
.

Flávio Codeço Coelho

+55(21) 3799-5551
Professor
Escola de Matemática Aplicada
Fundação Getulio Vargas
Praia de Botafogo, 190 sala 312
Rio de Janeiro - RJ
22250-900
Brasil

@fccoelho
Copy link

fccoelho commented Jan 6, 2016

here is a full example in ipython --pylab

plot([1,2,3])

Now if I do a matplotlib.use('Agg') or another non-qt backend, before importing pyplot, I get an import error:

ImportError: Gtk* backend requires pygtk to be installed.

@tacaswell
Copy link
Member

Because using --pylab implicitly import pyplot. We do not officially support switching gui backends once you have imported pyplot.

@fccoelho
Copy link

fccoelho commented Jan 7, 2016

I had another library importing pyplot before my call to matplotlib.use. Now I am able to switch backends.
Thanks for the help.

@tacaswell
Copy link
Member

I had a conversation with @WeatherGod about how to delay the import of the
gui tool kits until you make the first figure which would reduce pain like
this, but I do not think either of us had the bandwidth to do anything
about it.

On Thu, Jan 7, 2016, 06:45 Flávio Codeço Coelho notifications@github.com
wrote:

I had another library importing pyplot before my call to matplotlib.use.
Now I am able to switch backends.
Thanks for the help.


Reply to this email directly or view it on GitHub
#3623 (comment)
.

@WeatherGod
Copy link
Member

I have notes that I made while writing up my book about this idea, but I
have to find them and decode my awful handwriting...

On Thu, Jan 7, 2016 at 8:17 AM, Thomas A Caswell notifications@github.com
wrote:

I had a conversation with @WeatherGod about how to delay the import of the
gui tool kits until you make the first figure which would reduce pain like
this, but I do not think either of us had the bandwidth to do anything
about it.

On Thu, Jan 7, 2016, 06:45 Flávio Codeço Coelho notifications@github.com
wrote:

I had another library importing pyplot before my call to matplotlib.use.
Now I am able to switch backends.
Thanks for the help.


Reply to this email directly or view it on GitHub
<
#3623 (comment)

.


Reply to this email directly or view it on GitHub
#3623 (comment)
.

@mgrady3
Copy link

mgrady3 commented Apr 13, 2016

I have a working PyQt4 app that I have begun working on upgrading to PQt5; I am running into this same old issue of the missing figure positional argument.

My development details:
python 3.5 via anaconda in a separate environment.
I have installed pyqt5
I have installed matplotlib 1.5.1 np111py35_0 via conda
This insall requires Qt4 and PyQt4 to be installed, so after installing matplotlib I went back and ran 'conda remove qt' and 'conda remove pyqt'

This leaves me with an environment running python 3.5, matplotlib 1.5.1, with an installation of Qt5 and PyQt5.

I begin my code with

import matplotlib; matplotlib.use("Qt5agg", force=True)

then later in the code I have

self.LEED_IV_fig, (self.LEED_img_ax, self.LEED_IV_ax) = plt.subplots(1, 2, figsize=(6,6), dpi=100)

self.LEED_IV_canvas = FigureCanvas(self.LEED_IV_fig)

This fails with

Traceback (most recent call last):
File "/Users/Maxwell/PyCharmProjects/pLEASE/main.py", line 47, in <module>
main()
File "/Users/Maxwell/PyCharmProjects/pLEASE/main.py", line 31, in main
view = gui.Viewer()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 81, in __init__
self.init_UI()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 127, in init_UI
self.init_tabs()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 305, in init_tabs
self.init_LEED_Tab()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 315, in init_LEED_Tab
self.LEED_IV_canvas = FigureCanvas(self.LEED_IV_fig)
File "/Users/Maxwell/anaconda/envs/pyqt5/lib/python3.5/site-packages/matplotlib/backends/backend_qt4agg.py", line 76, in __init__
FigureCanvasQT.__init__(self, figure)
File "/Users/Maxwell/anaconda/envs/pyqt5/lib/python3.5/site-packages/matplotlib/backends/backend_qt4.py", line 71, in __init__
QtWidgets.QWidget.__init__(self)
TypeError: __init__() missing 1 required positional argument: 'figure'

Process finished with exit code 1`

The code can be seen at github.com/mgrady3/pLEASE in the branch dev_PyQt5
The code in question specifically comes from the file gui.py

I can try to come up with a minimal working example to recreate this in the mean time

EDIT
I believe I found the issue due to some mixed imports from FigureCanvasQtAgg still coming from the Qt4 backend.

@tacaswell
Copy link
Member

You are importing the qt4 backend (
https://github.com/mgrady3/pLEASE/blob/dev_PyQt5/gui.py#L38) explicitly.
The use call only affects which backend pyplot attempts to use (and we
strongly advise against mixing pyplot + your own embedding; it can work,
but can also break in surprising ways.).

The main difference between pyqt4 and pyqt5 is that with pyqt5 all of the
classes are cooperative so just calling super works, where as in pyqt4
you need to manually call each of the parent classes in MI.

The simple fix is to just change your imports an line 38 and 39 to be from
backend_qt5agg.

Tom

On Wed, Apr 13, 2016 at 11:39 AM M. Grady notifications@github.com wrote:

I have a working PyQt4 app that I have begun working on upgrading to PQt5;
I am running into this same old issue of the missing figure positional
argument.

My development details:
python 3.5 via anaconda in a separate environment.
I have installed pyqt5
I have installed matplotlib 1.5.1 np111py35_0 via conda
This insall requires Qt4 and PyQt4 to be installed, so after installing
matplotlib I went back and ran 'conda remove qt' and 'conda remove pyqt'

This leaves me with an environment running python 3.5, matplotlib 1.5.1,
with an installation of Qt5 and PyQt5.

I begin my code with

import matplotlib; matplotlib.use("Qt5agg", force=True)

then later in the code I have

self.LEED_IV_fig, (self.LEED_img_ax, self.LEED_IV_ax) = plt.subplots(1, 2, figsize=(6,6), dpi=100)

self.LEED_IV_canvas = FigureCanvas(self.LEED_IV_fig)

This fails with

Traceback (most recent call last):
File "/Users/Maxwell/PyCharmProjects/pLEASE/main.py", line 47, in
main()
File "/Users/Maxwell/PyCharmProjects/pLEASE/main.py", line 31, in main
view = gui.Viewer()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 81, in init
self.init_UI()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 127, in init_UI
self.init_tabs()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 305, in init_tabs
self.init_LEED_Tab()
File "/Users/Maxwell/PyCharmProjects/pLEASE/gui.py", line 315, in init_LEED_Tab
self.LEED_IV_canvas = FigureCanvas(self.LEED_IV_fig)
File "/Users/Maxwell/anaconda/envs/pyqt5/lib/python3.5/site-packages/matplotlib/backends/backend_qt4agg.py", line 76, in init
FigureCanvasQT.init(self, figure)
File "/Users/Maxwell/anaconda/envs/pyqt5/lib/python3.5/site-packages/matplotlib/backends/backend_qt4.py", line 71, in init
QtWidgets.QWidget.init(self)
TypeError: init() missing 1 required positional argument: 'figure'

Process finished with exit code 1`

The code can be seen at github.com/mgrady3/pLEASE in the branch dev_PyQt5
The code in question specifically comes from the file gui.py

I can try to come up with a minimal working example to recreate this in
the mean time


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub
#3623 (comment)

@mgrady3
Copy link

mgrady3 commented Apr 13, 2016

Thanks,
I realized that just a few moments before you posted.

Appreciate the help and quick response.

@ghost
Copy link

ghost commented May 7, 2017

I'm having this issue too, but even with an incredibly simple test... I cannot for the life of me get this working.

The backend set to qt5agg in matplotlibrc.. and this:

import matplotlib
matplotlib.use("Qt5agg", force=True)
from matplotlib import pyplot as plt

plt.plot([1, 2, 3], [4, 5, 6])
plt.show()

Results in this:

File "/usr/local/lib/python3.5/dist-packages/matplotlib/pyplot.py", line 3306, in plot
    ax = gca()
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/pyplot.py", line 950, in gca
    return gcf().gca(**kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/pyplot.py", line 586, in gcf
    return figure()
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/pyplot.py", line 535, in figure
    **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_qt5agg.py", line 44, in new_figure_manager
    return new_figure_manager_given_figure(num, thisFig)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_qt5agg.py", line 51, in new_figure_manager_given_figure
    canvas = FigureCanvasQTAgg(figure)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_qt5agg.py", line 242, in __init__
    super(FigureCanvasQTAgg, self).__init__(figure=figure)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_qt5agg.py", line 66, in __init__
    super(FigureCanvasQTAggBase, self).__init__(figure=figure)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_qt5.py", line 243, in __init__
    super(FigureCanvasQT, self).__init__(figure=figure)
TypeError: 'figure' is an unknown keyword argument

Using 2.0.1 with KDE Neon/Qt 5.7.1 and Python 3.5

@tacaswell
Copy link
Member

@arcooke I am pretty sure your issue is that you have pyqt4 installed (and not pyqt5). Check that you can import PyQt5.

If that does not solve it please try the mailing list, gitter, or creating a new issue.

@ghost
Copy link

ghost commented May 7, 2017

@tacaswell
Thanks a bunch, that was it.. I could have sworn I had that installed.

A bit off topic, but I did get some errors about missing icons when switching from TkAgg (the only one that worked for me) to Qt5Agg.. does this merit a new thread? I am using Papyrus-Dark icons and it seems to be trying to find a handful of specific icons

Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/16/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/22/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/24/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/32/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/48/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/64/"
Invalid Context= "stock" line for icon theme:  "/usr/share/icons/ubuntu-mono-dark/stock/128/"
Icon theme "Adwaita" not found.
Icon theme "Adwaita" not found.
Icon theme "Adwaita" not found.
Icon theme "Mint-X" not found.
Icon theme "elementary" not found.

image

@tacaswell
Copy link
Member

Yes. please make a new issue for that.

@ghost
Copy link

ghost commented May 7, 2017

Done, thank you for the help. 👍

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

7 participants