Skip to content

How to run PyQt applications within Spyder

Carlos Cordoba edited this page Oct 25, 2017 · 5 revisions

Example applications (that are based on this code)

PyQt5

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize    
     
class HelloWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
 
        self.setMinimumSize(QSize(100, 100))    
        self.setWindowTitle("Hello world") 
        
        centralWidget = QWidget(self)          
        self.setCentralWidget(centralWidget)   
 
        gridLayout = QGridLayout(self)     
        centralWidget.setLayout(gridLayout)  
 
        title = QLabel("Hello World from PyQt", self) 
        title.setAlignment(QtCore.Qt.AlignCenter)
        gridLayout.addWidget(title, 0, 0)
        
        menu = self.menuBar().addMenu('Action for quit')
        action = menu.addAction('Quit')
        action.triggered.connect(QtWidgets.QApplication.quit)
 
if __name__ == "__main__":
    def run_app():
        app = QtWidgets.QApplication(sys.argv)
        mainWin = HelloWindow()
        mainWin.show()
        app.exec_()
    run_app()

PyQt4

import sys
from PyQt4 import QtCore
from PyQt4.QtGui import QMainWindow, QLabel, QGridLayout, QWidget, QApplication
from PyQt4.QtCore import QSize    
     
class HelloWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
 
        self.setMinimumSize(QSize(100, 100))    
        self.setWindowTitle("Hello world") 
        
        centralWidget = QWidget(self)          
        self.setCentralWidget(centralWidget)   
 
        gridLayout = QGridLayout(self)     
        centralWidget.setLayout(gridLayout)  
 
        title = QLabel("Hello World from PyQt", self) 
        title.setAlignment(QtCore.Qt.AlignCenter)
        gridLayout.addWidget(title, 0, 0)
        
        menu = self.menuBar().addMenu('Action for quit')
        action = menu.addAction('Quit')
        action.triggered.connect(QApplication.quit)
 
if __name__ == "__main__":
    def run_app():
        app = QApplication(sys.argv)
        mainWin = HelloWindow()
        mainWin.show()
        app.exec_()
    run_app()

An explanation

The most common problem when running a QApplication multiple times inside Spyder is that a QApplication instance remains in the namespace of the IPython console kernel after the first run. In other words, when you try to re-run your application, you already have a QApplication instance initialized.

Trying to remove that instance will probably cause your program to get stuck in the blocking while-loop as suggested here, and using sys.exit() doesn't help since it's the same as trying to exit Python (and hence the IPython console).

In the code above then you can see that we make a function for the creation of the QApplication instance (to make it local and prevent it to get in the namespace of the kernel of the console). Another approach that could work in some cases is adding a validation for a QApplication instance with the method instance(). In the later case you probably will need to structure the main that creates the QApplication instance with something like this:

 if not QApplication.instance():
        app = QApplication(sys.argv)
    else:
        app = QApplication.instance() 

Useful info/issues/documentation of QApplication

Clone this wiki locally