I have a not very sophisticated but also not trivial Qt5 python application (the full thing is here: https://gitlab.com/rulrich/pydatagrab but see below for a minimal example)
My question is the following:
I have a QMainWindow where in the constructor I do many things, but also:
self.exitAct = QAction("Exit", self, shortcut="Ctrl+Q", triggered=self.close)
...
self.fileMenu = QMenu("File", self)
self.fileMenu.addAction(self.exitAct)
furthermore, I call a file dialog in the constructor
options = QFileDialog.Options()
fileName, _ = QFileDialog.getOpenFileName(self, 'QFileDialog.getOpenFileName()', '',
'Images (*.png *.jpeg *.jpg *.bmp *.gif *.yaml)',
options=options)
When I either press Ctrl+Q or click on File->Exit the same thing happens: the GUI disappears, there are no errors. But the process is kept alive and does not terminate. On Linux, when I start this in the shell, killing the process with Ctrl+C (SIGINT) even does not work (very strange), I have to terminate it with kill
(SIGTERM).
I don't have any special "close" method or functionality in my application. This is directly QMainWindow.close()
.
Initially I was 100% unclear where to start looking for the problem. However, with the help of this question here and the responses, I figured out it is the QFileDialog
itself that is causing the behavior. If I take this out, the application behaves normally.
The minimally reproducing code is here:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self, fileName=None):
super().__init__()
self.exitAct = QAction("Exit", self, shortcut="Ctrl+Q", triggered=self.close)
self.fileMenu = QMenu("File", self)
self.fileMenu.addAction(self.exitAct)
self.menuBar().addMenu(self.fileMenu)
self.openFile()
def openFile(self):
options = QFileDialog.Options()
fileName, _ = QFileDialog.getOpenFileName(self, 'QFileDialog.getOpenFileName()', '',
'Images (*.png *.jpeg *.jpg *.bmp *.gif *.yaml)',
options=options)
# load some data ...
# ...
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
=================================
Output of print(app.allWidgets())
(after fixing the problem):
[<PyQt5.QtWidgets.QMenu object at 0x7fb8e6ae49d0>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6ae4b80>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6ae4c10>, <PyQt5.QtWidgets.QMenu object at 0x7fb8e6ae4ca0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6ae4d30>, <PyQt5.QtWidgets.QPushButton object at 0x7fb8e6ae4160>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6ae4dc0>, <PyQt5.QtWidgets.QLineEdit object at 0x7fb8ee6ea790>, <PyQt5.QtWidgets.QMenu object at 0x7fb8e6ae4790>, <PyQt5.QtWidgets.QLineEdit object at 0x7fb8ee6eae50>, <PyQt5.QtWidgets.QFrame object at 0x7fb8e6ae4e50>, <PyQt5.QtWidgets.QScrollArea object at 0x7fb8ee6ea5e0>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6ea670>, <PyQt5.QtWidgets.QLabel object at 0x7fb8e6ae40d0>, <PyQt5.QtWidgets.QToolButton object at 0x7fb8e6ae4ee0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6ae4f70>, <PyQt5.QtWidgets.QLineEdit object at 0x7fb8ee6eac10>, <PyQt5.QtWidgets.QFrame object at 0x7fb8e6af5040>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af50d0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5160>, <PyQt5.QtWidgets.QLineEdit object at 0x7fb8ee6ea9d0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6ae4af0>, <__main__.MainWindow object at 0x7fb8ee6ea160>, <PyQt5.QtWidgets.QLabel object at 0x7fb8e6ae4040>, <PyQt5.QtWidgets.QComboBox object at 0x7fb8ee6ea430>, <PyQt5.QtWidgets.QFrame object at 0x7fb8e6af51f0>, <PyQt5.QtWidgets.QListView object at 0x7fb8e6af5280>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5310>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af53a0>, <__main__.DataArea object at 0x7fb8ee6ea550>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5430>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af54c0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5550>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af55e0>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5670>, <PyQt5.QtWidgets.QMenuBar object at 0x7fb8e6ae4a60>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6eadc0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5700>, <PyQt5.QtWidgets.QFrame object at 0x7fb8e6af5790>, <PyQt5.QtWidgets.QListView object at 0x7fb8e6af5820>, <PyQt5.QtWidgets.QComboBox object at 0x7fb8ee6eab80>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af58b0>, <PyQt5.QtWidgets.QListView object at 0x7fb8e6af5940>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af59d0>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6eaaf0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5a60>, <PyQt5.QtWidgets.QComboBox object at 0x7fb8ee6ea4c0>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5af0>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5b80>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5c10>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5ca0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5d30>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6eaca0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6af5dc0>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6ea820>, <PyQt5.QtWidgets.QLabel object at 0x7fb8ee6ea940>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5e50>, <PyQt5.QtWidgets.QScrollBar object at 0x7fb8e6af5ee0>, <PyQt5.QtWidgets.QComboBox object at 0x7fb8ee6ea700>, <PyQt5.QtWidgets.QListView object at 0x7fb8e6af5f70>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6ae41f0>, <PyQt5.QtWidgets.QWidget object at 0x7fb8e6afc040>, <PyQt5.QtWidgets.QMenu object at 0x7fb8e6ae48b0>]
Further simplified MRE:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self, fileName=None):
super().__init__()
key = QShortcut(QKeySequence("Ctrl+Q"), self)
key.activated.connect(self.close)
self.openFile()
def openFile(self):
fileName, _ = QFileDialog.getOpenFileName(self, 'QFileDialog.getOpenFileName()', '',
'Images (*.png *.jpeg *.jpg *.bmp *.gif *.yaml)')#)
#,options=QFileDialog.DontUseNativeDialog)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
-> no change in behaviour.