I am following a tutorial on pyqt, and got this code:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
cb = QCheckBox('Show title', self)
cb.move(20, 20)
cb.toggle()
cb.stateChanged.connect(self.changeTitle)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Checkbox')
self.show()
def changeTitle(self, state):
if state == Qt.Checked:
self.setWindowTitle('Checkbox')
else: self.setWindowTitle('Unchecked!')
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I'm using PyDev on Eclipse. Suffice it to say that the code runs fine, but what is awkward is that PyDev underlines anything Qt/Q with a red line which when hovered over says Undefined variable: <..>. If it is undefined then how is it that my code runs without errors? Clearly this ought to be a problem with PyDev. I've removed the python interpreter (it was pointing to python2.7 instead of 3.4) and readded it as the correct version; but that didn't work. Interestingly enough, it recognises PyQt4 and insists on using widgets from that instead of PyQt5.
Just so you guys are aware, the code sample above is from another laptop which had PyQt5 as well. Both projects were from PyDev, and both had Ubuntu 15.04. It's possible that my importing of the project on my current machine messed up PyDev parsing the required libraries. Does anyone have a solution as to why PyDev doesn't recognise PyQt5?
I had the same problem. These steps worked for me.
Set the environment variable: export QT_API=pyqt5 (or whatever as appropriate)
restart eclipse so that picks up the new environment setting, and then add PyQt5 to the list of forced builtins for the interpreter (Window->preferences->pydev->interpreters->python interpreters) or look here http://www.pydev.org/manual_101_interpreter.html for more details.
The following SO question tipped me off to the presence of the variable: Setting up IPython Qtconsole with PyQt5. Before I set it, I as able to get some completion to work just by adding 'PyQt5' to the builtins, but it would not, for example, provide the full list of completions to something likefrom PyQt5.QtGui import, even though ipython stand-alone would. Further, the python console in pydev had the same problem and calling module_completion("from PyQt5.QtGui import Q") from Ipython.core.completerlib produced the same incomplete list. In the end, I guessed that since pydev was loading PyQt4 for the gui event loop (also configurable in the interpreter settings), there was a namespace conflict when it tried to introspect the Qt5 modules, causing it to bail out before it could build the full list of completions. Setting the environment variable causes pydev to load pyqt5 instead of the default pyqt4. I haven't checked, but it seems likely that set this way pydev will have problems completing pyqt4 references.
For all those lonesome internet wanderers trying to figure out how to integrate eclipse, pydev, and pyqt5 on Linux, I bring you my method from start to finish.
Eclipse, PyQt5, and PyDev on Linux
Install python v3.6
Install eclipse from eclipse.org
In eclipse, click Help->Install New Software
Click Add...
Add in software source "http://www.PyDev.org/updates" to the available software sources
Call it PyDev
Click on PyDev checkbox
Install it by clicking Next
Download PyQt5
Download SIP
Install SIP first
Install PyQt5
Reconfigure eclipse to use PyQt5
Click on Window→Preferences→PyDev→Interpreters→Python Interpreters
Click on Advanced Auto-Config
Rename interpreter to “python3.6”
Click on Libraries tab
Click on New Folder
Add in “/usr/lib/x86_64-linux-gnu/qt5/plugins”
Add in “/usr/lib/x86_64-linux-gnu/qt5/libexec”
Add in “/usr/lib/x86_64-linux-gnu/qt5/bin”
Click Apply
Click Apply and Close
Restart eclipse
Profit!
This will allow you to get the tab code completion in eclipse when developing pyqt5 applications.
Related
Simply stated I have a simple python application which generates random passwords. This application was originally written using Tkinter and currently works. I am trying to improve the GUI interface by employing PyQt5. My efforts, so far have resulted in an application that runs from within my IDE (Spyder) and can also be run by invoking python from the commandline with the fullpath of the python script.
It should be noted this works for the Tkinter as well as the PyQt implementation.
My next step was to define a shortcut on the desktop to execute this script and have a window appear allowing creation of a password. The shortcut for the Tkinter script performs as expected and results in a window appearing. The script for the PyQt5 based script does not work. The only differences between the scripts are the target files being invoked by the script. Also both script files are in the same directory. This is a side by side image of the shortcut properties.
Here is a very simplistic example of the Puqt5 code. This code exhibits the same characteristics as the original in that it runs in the IDE as well as directly from Python in the CMD window but will not execute from a shortcut icon.
"""
Created on Wed Sep 9 10:37:46 2020
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget
def main():
app = QApplication(sys.argv)
w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Has anyone else had this type of problem or can anyone suggest an approach for determining what is the cause and solution
everything works on Windows 7
It work when invoked from a shortcut on Win &, hmm that's very strange.
I tested it on Windows 10 also works.
Thanks for the helpful suggestions as well as your efforts to test this problem on your own systems. I finally found an answer that satisfies my needs. I used pyinstaller to create an executable and then launch the executable from a desktop shortcut. This works, so I am considering my question closed.
I can't manege to get the images or icons loaded. When I run the app in VScode the app works, just without the images. The Icons even have the space but there is nothing in the space where the icon is supposed to be. But running it in the Command Terminal works like it is supposed to.
Using the 'os.path. ...' method, and running it in VScode works every time. But why is it like that?
And, how will the os.path method affect the app when I run it alone? I.e. when I don't run it though the IDE or the Command Prompt (I'm planing to make it a stand alone app, just for fun).
A sample of code that works, the whole app is a bit bigger. (but same principles):
import sys
import os
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
current_directory = os.path.dirname(os.path.realpath(__file__))
widget = QLabel("")
image = QPixmap(os.path.join(current_directory, "39487.jpg" ))
widget.setPixmap(image)
widget.setScaledContents(True)
self.setCentralWidget(widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
Now why when i run this code, the images show. Yet when I remove the os.path method it does not work in the IDE. Running the second version in the Prompt does work though.
Why does the IDE load the code different than the Prompt?
The relative paths in python with respect to where the python command is executed, by default VScode launches python in the root folder of the project so it is not necessarily launched in the script folder, instead you use the command promt from the folder where There is the script and the icons, if you were to run from a higher folder you would also have the same problem. Due to the error that causes relative paths it is better to use absolute paths either explicitly or by constructing it using os.path.
I'm trying to run an app with PySide2 from Spyder 3.2.8 and Python 3.6.4 in Anaconda in a macOS 10.13.4.
attempt N°1
After having seen this stackoveflow page and this github page I changed my graphic backend from Inline to Automatic in Python > Preferences > IPython Console > Graphics and I tried to run the following script (script N°1):
script N°1
import sys
from PySide2.QtWidgets import *
# Create a Qt application
app = QApplication.instance()
if app is None:
print("print something")
app = QApplication(sys.argv)
# Create a Label and show it
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
app.exec_()
but got the following error message after running it:
Importing PySide2 disabled by IPython, which has
already imported an Incompatible QT Binding: pyqt5
There are similar reported issues here with matplotlib and here with ipython but it didn't help me (or I couldn't implement it properly). Then I tried to implement the content of this page about qtpy by changing the script N°1 in the following way:
script N°2
import os
os.environ['QT_API'] = 'pyside2'
from qtpy.QtWidgets import *
import sys
# Create a Qt application
app = QApplication.instance()
if app is None:
print("print something")
app = QApplication(sys.argv)
# Create a Label and show it
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
app.exec_()
attempt N°2
With Inline selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°2 , the app launches and I got print something printed in to the console. When closing the app, I got Out[1]: 0 in the console. However when I run the script again, no error message appears in the console but the window of the app doesn't show-up
attempt N°3
This time with Automatic selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°2 the first time, the app didn't launch and I got the following error message
/anaconda3/lib/python3.6/site-packages/qtpy/__init__.py:178: RuntimeWarning: Selected binding "pyside2" could not be found, using "pyqt5"
'using "{}"'.format(initial_api, API), RuntimeWarning)
Out[2]: -1
attempt N°4
With Automatic selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°1 after having changed the line from PySide2.QtWidgets import * to from PyQt5.QtWidgets import *: The app didn't launch and I got the following error message
Out[1]: -1
attempt N°5
With Inline selected in Python > Preferences > IPython Console > Graphics. When I ran the script N°1 after having changed the line from PySide2.QtWidgets import * to from PyQt5.QtWidgets import *: The app launches and I got print something printed in to the console. I closed the app and got Out[1]: 0 in the console. However when I run the script again, no error message appears in the console but the window of the app doesn't show-up
N.B. this question is the continuation of that question
(Spyder maintainer here) Since the ipykernel package (which is used by Spyder to run code in its consoles) doesn't have event loop support for PySide2 as of May/2018 (as can be seen here), you won't be able to run PySide2 code inside Spyder, no matter what you try.
Notes:
The Automatic backend tries to select a suitable event loop for you, in this order: Qt5, Qt4, Tk and Inline. That's why it doesn't work in your case.
Every time you change a Graphics backend in Spyder, you need to restart the kernel of the console you want to run your code in. That's because you can only use one backend per console session (this is a limitation imposed by ipykernel, not by us). It's clear from your question that you're not doing that.
We're aware we fail to inform users when a kernel restart is necessary. We'll try to address that in our next major version (Spyder 4), to be released in 2019.
If you already know about qtpy, please use it to develop your apps instead of using PySide2 directly. That way you could work with PyQt5 for development in Spyder, but PySide2 for deployment, since qtpy takes care of working seamlessly with whatever binding is available.
I have created a large python program with GUI based on PyQt4. I would like the package to run both in an IPython notebook (old installation with Python 2.7 on windows), Jupyter notebook (Python 3.5 installed recently with Anaconda), and as a python program passed on the command line. I'm having problems in running the code in Jupyter notebook (see directly at the bottom).
My module mymodule.py looks like this (extremely simplified, about 10k lines before the show from many other python files):
from PyQt4 import QtCore, QtGui
class MyModule(object):
def __init__(self):
self.window = QtGui.QMainWindow()
self.window.show()
The typical usage from command line is
python myscript.py
with the following file myscript.py
from PyQt4 import QtCore, QtGui
import mymodule
m = mymodule.MyModule()
APP = QtGui.QApplication.instance()
APP.exec_()
This works fine. I understand that APP.exec_() is needed to start some kind of EventLoop that works through the Gui interaction events.
In an IPython notebook, the user typically does
import mymodule
m = mymodule.MyModule() # opens the gui
# this still leaves the console active to allow things like this:
m.change_color("red")
I can run this without problems, where I understant that IPython somehow takes care of the EventLoop behind the scene.
Now, running the same commands in Jupyter notebook, a window opens, but freezes before allowing any user interaction. So I believe that Jupyter notebook does not treat the events properly because I did not tell it to do so. One way I have found is executing the command %pylab before running my code. However, I frequently run into related problems with this, for example when running %pylab and %matplotlib inline in direct succession before starting my program, this leads to freezing again once I load my code (curiously, reversing the order of the two magical commands works again). Also, I do not want to force the user of my program to execute %pylab in each new notebook if it can be avoided (also because I believe this requires a matlab installation, which is not a requirement of my program).
What code must I add in mymodule.py to make things compatible with the described user code in Jupyter notebook? Can anyone explain more clearly how IPython notebook and Jupyter notebook manage the QEventLoop/QApplication (or whatever is the important concept here) differently, and how the magic commands mess with this? I am afraid of hidden bugs in my program because of this, and would like to make it as robust as possible to not frustrate the users.
Here is a working solution that allows to run the code without distinguishing between different IPython / Jupyter versions and 'raw' Python. My __init__.py file contains this section at the beginning:
# enable IPython QtGui support if needed
try:
from IPython import get_ipython
get_ipython().magic('gui qt')
except BaseException as e:
# issued if code runs in bare Python
print('Could not enable IPython gui support: %s.' % e)
# get QApplication instance
from PyQt4 import QtCore, QtGui
APP = QtGui.QApplication.instance()
if APP is None:
print('Creating new QApplication instance "mymodule"')
APP = QtGui.QApplication(['mymodule'])
The script running on raw Python then only needs this:
import mymodule # imports the above code
from PyQt4 import QtCore, QtGui
if __name__ == '__main__':
QtGui.QApplication.instance().exec_()
I found no use case where this does not work.
Under OS X, using the zetcode example for menubar, if one runs this from the command line:
$ python menubar.py
the application starts, but at the bottom of the window stack. This can be fixed by adding
self.raise_()
to the code.
However, the application is still not immediately active. The terminal application menubar still shows, not the pyqt menubar.
The only way to get the pyqt menubar to show is to switch away from the pyqt application or terminal application and back again.
Is this expected behavior? Is there anyway to fix this so the pyqt application immediately becomes active, i.e. the pyqt menubar immediately shows upon execution.
Versions: OS X 10.9, Qt 4.8.6, PyQt 4.11.3, SIP 4.16.5, python 2.7.8
The identical problem affects some apps bundled by PyInstaller. The following blog post discusses the fix, however the fix is in terms of the PyInstaller boot loader, which would not be directly relevant to your code, but it might be informative.
http://dvitonis.net/blog/2015/01/07/menu-bar-not-visible-when-building-pyqt-app-bundle-pyinstaller-mac-osx-mavericks-yosemite/
The problem relates to use of TransformProcessType() which is discussed in this linked article:
http://www.sheepsystems.com/developers_blog/TPT-show-menu.html
I do not know what Qt method would relate to the Mac OS TransformProcessType() but you might experiment with calling QWidget.setWindowState() in your mainwindow's __init__().
I was experiencing this behavior, but only when I launch with a --nosplash option to skip the splash screen in my application.
That gave me a hint, and I developed this workaround using a 'dummy' splash screen:
widget = QtGui.QMainWindow() # or whatever your main window class is
dummy = QtGui.QSplashScreen()
dummy.show()
dummy.finish(widget)
widget.show()
widget.raise_()