I am running some code using PyQt4, and I would like to plot a figure using its data. But when I try to do that, it will report
QPixmap: Must construct a QGuiApplication before a QPixmap
Below is the code:
from PyQt4 import QtCore
import sys
import matplotlib.pyplot as plt
import numpy as np
def run():
#here is some code, I delete them since they are useless for this question
return data1 #data1 is a list with 30 elements
app = QtCore.QCoreApplication(sys.argv)
client.finished.connect(app.quit)
QtCore.QTimer().singleShot(0,lambda:client.timed_range_stream(5000))
app.exec_()
fig = plt.figure()
ax1 = fig.add_subplot(111)
data2 = run()
datalen = np.linspace(0,10,len(data2))
ax1.plot(datalen,data2,lw = 2)
plt.show()
Since the matplotlib is using pyqt4 as backend, I am so confused why this error happened. It should create a QGuiApplication automatically. I mean whether I use pyqt4 before or not, the code below 'app.exec_()' should create a QGuiApplication automatically. Please point out if I am wrong.
Really appreciate your help! Please give me some advice.
The complaint by PyQt is that you are not running a Gui EventLoop. app.exec_() sure starts an event loop, but that depends on what app is. In your case its QCoreApplication object. How do you expect it to start a Gui EventLoop? It's like buying a saucepan and expecting it to cook pizza.
matplotlib is based on PyQt for sure. I'm sure you can use it in console only applications as well. Hence PyQt will not be able to tell if you want a gui or a console app.
QCoreApplication is used when you are writing a console-based application. Fewer events and processes to manage. If you want to show a window, even a simple one, it takes much more work. And the beast to handle that extra work in QGuiApplication
Now to the Qt version. You are using PyQt4, but the complaint says you need to create a QGuiApplication. However, there is no QGuiApplication or any reference to it in Qt4/PyQt4. This leads me to believe that, your matplotlib copy might be using PyQt5, or PyQt5 dependency comes in from some obscure source, I'm not sure. Check the details of the PyQt version used.
If you are using PyQt4 add from PyQt4 import QtGui in the beginning.
Then change the app = QtCore.QCoreApplication(...) to app = QtGui.QApplication(...).
In case of PyQt5 add from PyQt5 import QtGui, QtWidgets in the beginning.
Then change the app = QtCore.QCoreApplication(...) to app = QtWidgets.QApplication(...).
That'll solve your problem.
PS: Remember, you cannot mix PyQt4 and PyQt5.
Related
I'm quite new to pyqt and pyqtgraph so my apology if I'm missing basic things.
I have python program that acquires and plots data, where GUI is implemented by enaml. However the speed of MPL Canvas (matplotlib) was intolerably slow for realtime plotting application, therefore I wish to enhance the performance utilizing pyqtgraph. Immediate conflict seen is that enaml needs to have
from enaml.qt.qt_application import QtApplication
app=QtApplication()
while in order to use pyqtgraph the following seems necessary.
from pyqtgraph.Qt import QtGui, QtCore
app = QtGui.QApplication([])
Can enaml and pyqtgraph coexist or can at least embed pyqtgraph within the enaml thread? If someone can give me a clue it would be a great help. Thanks.
Yes they can exist together. You can create your own declaration and toolkit widgets or use the one from enamlx.
There's an example https://github.com/frmdstryr/enamlx/blob/master/examples/plot_area/plot_area.enaml
I am working for the first time towards the implementation of a very simple GUI in PyQt5, which embeds a matplotlib plot and few buttons for interaction.
I do not really know how to work with classes so I'm making a lot of mistakes, i.e. even if the functionality is simple, I have to iterate a lot between small corrections and verification.
For some reason I would like to debug, however, the whole process is made much, much slower by the fact that at any other try, the python kernel dies and it needs restarting (all done automatically) several times.
That is, every time I try something that should last maybe 5 secs, I end up spending a minute.
Anybody know where to look to spot what is causing these constant death/rebirth circles?
I have been using spyder for some time now and I never experienced this behaviour before, so I'm drawn to think it might have to do with PyQt, but that's about how far I can go.
This issue is tracked here
You can learn all the details there, but in a nutshell when running from inside spyder - which itself is a QApplication, the main loop should read:
if __name__ == '__main__':
import sys
from PyQt5 import QtWidgets
fig1 = Figure()
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
The if/then check on the existence of a QApplication avoids a segmentation fault which happens if one tries to launch multiple instances at one time, as explained here
I had a similar problem and found that my application only worked when the graphics settings inside Spyder are set to inline. This can be done at Tools -> Preferences -> IPython console -> Graphics, now change the Backends to inline.
Hope this helps.
I'm trying to show a splash screen as soon as possible while my app is importing by doing something like this
import wx, wx.lib.agw.advancedsplash as AS, sys, os, matplotlib
matplotlib.use('WXAgg')
from threading import Thread
#some function definitions
class application(wx.Frame):
#the UI code here
class mod(Thread):
#blah blah
if __name__ == "__main__":
app = wx.App(redirect=True, filename="logfile.txt")
image = wx.Image("splash.png")
image.ConvertAlphaToMask()
bitmap = wx.BitmapFromImage(image)
splash = AS.AdvancedSplash(None, bitmap=bitmap, timeout=4000, agwStyle=AS.AS_TIMEOUT | AS.AS_CENTER_ON_SCREEN)
import time
import telnetlib
import ownmodule
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
from matplotlib.figure import Figure
frame = application(None, -1, "AdvancedSplash Test")
app.MainLoop()
but the only thing I get is the shape in gray of the image I chose, then the UI loads and the actual image fills up the gray shape in a flash and disappears timed out. It's like the splash screen shows but the image doesn't load until the main frame does.
What it should happen is to show immediately the image, not only the shape. Somebody know what is happening and how to solve it?
Also it would be great to not time out the splash screen but destroy it right before the main UI appears.
Since the MainLoop is not running then there is no way for events to be delivered to the window, including the splashscreen's EVT_PAINT event that will draw the bitmap.
The wx.Yield function will run a temporary event loop so adding a call to that after creating the splashscreen will let it paint itself and may be sufficient for your needs. One downside is that if there needs to be another paint event while you are doing your other startup code then it won't happen unless you do another wx.Yield, and depending on what other kinds of events may be triggered in those yields, you may have to worry about possible reentrancy problems.
Another approach would be to go ahead and jump into the MainLoop and then run the rest of your startup code in a CallAfter, or another thread, or whatever makes sense for your application.
I am trying to run through some pyqt5 tutorials in the ipython notebook, but have an issue where every second time I run a code block the kernal undergoes a forced restart. Here is the smallest code which causes the problem:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
I am running the Ipython3 notebook and python 3, as well as pyqt5, and using Ubuntu 14.04. It should be noted that this problem does not occur when running this same code via a script in terminal.
Some other unrelated questions have suggested that my problem could be due to sys.exit() messing with the instance of python(I hope that is the correct term) instead of just closing my pyqt application. This happens the first time I run the code, so that the second time it runs the kernel is forced to restart. Is this the problem? and if so how do I work around this?
If more info is required, please ask.
I tried out Taar's solution but still got a dead kernel after calling the cell with main more than twice.The problem is creating multiple Qapplications, this crashes the notebook.
There is multiple solutions I found, but to just being able to run a qt application use the following in the first cell:
%gui qt
from PyQt5.QtWidgets import QApplication, QWidget
and in the second cell:
if __name__ == '__main__':
w = QWidget()
w.setWindowTitle('Simple')
w.show()
You can call the second cell as many times as you want and it will work. the magic line %gui qt opens a QApplication for your notebook.
If you need more control (like being able to exit() it) there is various solutions that amount to checking if there is a Qapplication instance open. Here is an example:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5 import QtCore
second cell:
if __name__ == '__main__':
app = QtCore.QCoreApplication.instance()
if app is None:
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle('Simple')
w.show()
app.exec_()
This method does require closing the window before rerunning it (else they will be queued up: run 3x without closing the window, now you need to close the window 3x in a row). It will at least get you started with a properly loaded screen upon executing the cell. (anyone feel welcome to correct this example).
Some references for the second example: here, and here. But I don't know enough about how the qt gui interacts with the notebook to solve any problem with the above example.
I'm definitely in need of your help guys.. As in really.
My laptop has been stolen and I didn't have a backup of my
pyqt phonon video player that I made a year ago. I forgot how and what to do to recreate it.
I only know some key things to do for it to work. So please help me out.
From what i can remember I need to
Set backend capabilities (set phonon backend to windows media player?)
Install the required codecs (which i dont have a copy of)
Code the program (and sadly I forgot how to play a video)
If there's someone out there who have a working sample python videoplayer,
can you please share it with me?
I'm trying it right now and my sample doesn't work at all
from PyQt4.phonon import Phonon
media_source = phonon.Phonon.MediaSource("C:\\Sample.avi")
self.ui.videoPlayer.load(media_source)
self.ui.videoPlayer.play()
Please help me. And thank you very much to you guys.
I'm using python 2.6 and qt version 4.9. Now I'm coding on a virtual box windows XP
EDIT:
got a following sample with this problem but..
having this error when loading a file.
"The Operation Cannot Be Performed Because the Pins Are Not Connected"
This maybe because I'm using a virtual box in Ubuntu?
Don't forget to show() the videoplayer. For the rest, in my experience Phonon often has trouble finding the codecs needed to play videos on Windows. Installing K-Lite codec pack might work in that situation.
Here's a self-contained example that does work for me (Windows Vista32, Python 2.6.5, PyQt 4.7.3).
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
app = QtGui.QApplication(sys.argv)
vp = Phonon.VideoPlayer()
media = Phonon.MediaSource('C:\\video.mp4')
vp.load(media)
vp.play()
vp.show()
sys.exit(app.exec_())
Edit:
Multiple people have recently commented that the above code no longer gives the desired behavior. I haven't worked with PyQt in ages, but I suspect that one of the updates might have changed Phonon functionality.
According to the commenters, vp.show() now needs to be called before Phonon.MediaSource(), i.e.:
...
vp = Phonon.VideoPlayer()
vp.show()
media = Phonon.MediaSource('C:\\video.mp4')
vp.load(media)
vp.play()
sys.exit(app.exec_())