PyQT exit error in SPYDER - python

This is PyQT code that I have to be executed in Spyder. The first time, I executed it, it works well. On the second time, it says:
QWidget: Must construct a QApplication before a QPaintDevice "
I searched for solution but nothing worked for me.
from PyQt4 import QtGui, QtCore
import sys
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.button = QtGui.QPushButton('Test', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
def handleButton(self):
print ('Hello World')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
#sys.exit(app.exec_())
I even commented sys.exit() which some people proposed. Could someone help me to get rid of this error as I am restarting the kernel every other time to execute.

First, your example is not really minimal. You'll observe, that
from PyQt4 import QtGui
if __name__ == '__main__':
app = QtGui.QApplication([])
w = QtGui.QWidget()
w.show()
app.exec_()
already does the trick.
My guess is that the console in which you let this script run twice is not deleting the QApplication (type app in the console you see the variable is still there).
In the second run, the newly created QApplication interferes with the still existing from the old run. They all run within the same console and it depends a bit on what spyder does when running a file.
To circumvent this delete the app before another run:
del app

Related

Window closes immediatelly after run

My code calls one window with a button. When the button is clicked, call another window. But the second window closes immediately
"basic" and "windows_two" are .py libraries genereted by pyuic5 from .ui files
import basic, windows_two
from PyQt5 import QtCore, QtGui, QtWidgets
if __name__ == "__main__":
#Declarations
import sys
app = QtWidgets.QApplication(sys.argv)
def Call_Second_Window():
#Second Screen
Form = QtWidgets.QWidget()
ui = windows_two.Ui_Form()
ui.setupUi(Form)
Form.show()
def Call_Main_Window():
#MainWindow
MainWindow = QtWidgets.QMainWindow()
ui = basic.Ui_MainWindow()
ui.setupUi(MainWindow)
ui.printButton.clicked.connect(Call_Second_Window) #click event to second window
MainWindow.show()
sys.exit(app.exec_())
Call_Main_Window()
Whats wrong?
Thanks
Whenever a variable is local it gets "garbage collected" as soon as the function returns; this means that everything the variable might reference to will also be (possibly) deleted too.
What is happening in your case is that while the windows is correctly created, it will be immediately deleted (due to the garbage collection) when the Call_Second_Window returns (just after Form.show()).
To avoid that there is only one solution: make the reference to the object persistent. There are various approaches to achieve that, depending on the situation.
Unfortunately your code is a bit unorthodox (especially from a PyQt perspective), so I'm "refactoring" it in order to make it more standardized, better object oriented and, also importantly, easily readable.
import basic, windows_two
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = basic.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.printButton.clicked.connect(self.call_Second_Window)
self.secondWindow = None
def call_Second_Window(self):
if not self.secondWindow:
self.secondWindow = SecondWindow()
self.secondWindow.show()
class SecondWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.ui = windows_two.Ui_Form()
self.ui.setupUi(self)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
Note: As you can see, I changed the name of call_Second_Window with a lower "c", and that's because capitalized names should only be used for classes and constants, while function names should always start with a lower case. This is again for readability, which is very important in programming and one of the core principles of python. Read more about this and other important topics on the official Style Guide for Python Code.

Can't Kill PyQT Window after closing it. Which requires me to restart the kernal

I guess that I am not closing my PyQT5 Window correctly. I am using spyder (3.3.5) which I have installed with anaconda, to program a pyqt5 program. I am using qt creator to design my ui file, which I load using the loadUi function in pyqt package. Everything works fine with the code, until I need to close it. I close the window via the close button (the x button in the top right). The window itself is closed, but it seems like the console (or shell) is stuck, and I can't give it further commands or to re run the program, without having to restart the kernel (to completely close my IDE and re opening it).
I have tried looking for solutions to the problem in the internet, but none seems to work for me. Including changing the IPython Console > Graphics to automatic.
Edit: Also Created an issure:
https://github.com/spyder-ide/spyder/issues/9991
import sys
from PyQt5 import QtWidgets,uic
from PyQt5.QtWidgets import QMainWindow
class Mic_Analysis(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui=uic.loadUi("qt_test.ui",self)
...
if __name__ == "__main__":
def run_app():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app=QtWidgets.QApplication.instance()
mainWin=Mic_Analysis()
mainWin.show()
app.exec_()
run_app()
If someone have any suggestion I would be very happy to hear them.
For me, it helped to remove the 'app.exec_()' command.
But then it closes immediatly when running the code. To keep the window open, I needed to return the MainWindow instance to the global scope (or make it a global object). My code looks like this:
from PyQt5 import QtWidgets
import sys
def main():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
main = MainWindow()
main.show()
return main
if __name__ == '__main__':
m = main()
Try adding :
app.setQuitOnLastWindowClosed(True)
to your main() function
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Surprizinglly, for me this works well. No QApplication is needed.
It seems to work in another thread.
from PyQt5 import QtWidgets,uic
class Ui(QtWidgets.QDialog):
def __init__(self):
super().__init__()
uic.loadUi('./test.ui',self)
self.show()
w=Ui()

how to restart the app with single process?

I want to restart my app, but I follow the tutorial and add systemtray icon. every time restart the app, the systemtray not disappear, I found the app not really restart by some reason.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
EXIT_CODE_REBOOT = 122
def __init__(self):
super().__init__()
self.restart_button = QPushButton('restart')
self.restart_button.clicked.connect(self.onRestart)
self.setCentralWidget(self.restart_button)
self.systray = QSystemTrayIcon(self)
icon = self.style().standardIcon(QStyle.SP_TrashIcon)
self.systray.setIcon(icon)
self.systray.show()
def onRestart(self, checked):
QApplication.exit(self.EXIT_CODE_REBOOT)
if __name__ == '__main__':
currentExitCode = MainWindow.EXIT_CODE_REBOOT
while currentExitCode == MainWindow.EXIT_CODE_REBOOT:
app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
currentExitCode = app.exec()
app = None
each time restart the app, the previous system tray always existing, it is like it start an other process, I want the only process and not consuming any resources.
I tried your code and it works fine on Linux, but I also found similar reports (like this) about persistent icon after quit on Windows.
While doing a self.systray.hide() before quitting should be fine enough, I think that deleting the object from Qt's side (not by using del) might be better:
def onRestart(self, checked):
self.systray.deleteLater()
QApplication.exit(self.EXIT_CODE_REBOOT)

Can't use fcitx with self-written Qt app

I am learning pyqt5 and somehow I can't use fcitx in the text box created by QTextEdit or QLineEdit although fcitx works normally with other Qt apps like goldendict or kate. But later I found out that fcitx also doesn't work with another Qt app named Retext which uses Qt 5.10. Maybe this has something to do with the latest version of Qt or so I think.
Here's my code, just a simple textbox and nothing else:
import PyQt5.QtWidgets as QtWidgets
import sys
class App(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.text = QtWidgets.QTextEdit()
self.initUI()
def initUI(self):
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.text)
self.setLayout(vbox)
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Thanks to #ekhumoro, I know how to fix this. Just enable input method by adding this line to the __init__ function:
self.setAttribute(Qt.WA_InputMethodEnabled)
Then do this:
cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/fcitxplatforminputcontextplugin.so ~/.local/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforminputcontexts
sudo chmod +x ~/.local/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforminputcontexts/fcitxplatforminputcontextplugin.so

Python has stopped working in PyQt application

code like the following .After it running for about half a minute ,then close the window, then the "Python has stopped working" dialog pops up(you had better try more than once. )
I wonder why this happen ?any solution to this ?
​
Tested on Windows with PyQt4-4.11.3-gpl-Py3.4-Qt4.8.6-x32.exe
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowIcon(QIcon("./wa.png"))
self.createTrayIcon()
def createTrayIcon(self):
self.trayIcon = QSystemTrayIcon()
self.trayIcon.setIcon(self.windowIcon())
self.trayIcon.show()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
I do my PyQt work on linux, so there might be differences, but usually I construct my MainWindow with the following call:
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
...
I can run your code in python3, but after I exit I get the Segmentation Fault. If I change the constructor to what I indicated above the Fault is not reproduced.
Hope this helps

Categories

Resources