I'm working though the pyqt5 tutorial found here Zetcode, PyQt5
As an exercise for myself I'm trying to expand on an example so that I am presented with the same dialog message box regardless of method used to close the app:
The dialog message box is implemented in the closeEvent
method, full script provided at the end.
I'm having two issues:
1. When clicking 'Close' button, instead of just quitting, I want to call closeEvent
method including message box dialog.
I have replaced a line of the example code for the 'Close' push button:
btn.clicked.connect(QCoreApplication.instance().quit)
And instead am trying to call the closeEvent
method which already implements the dialog I want:
btn.clicked.connect(self.closeEvent)
However when i run the script and click the 'Close' button and select the resulting 'Close' option in the dialog i get the following:
Traceback (most recent call last):
File "5-terminator.py", line 41, in closeEvent
event.accept()
AttributeError: 'bool' object has no attribute 'accept'
Aborted
Can anyone advise what I'm doing wrong and what needs to be done here?
2. When hitting the escape key somehow the message box dialog is presented and works just fine.
Ok, it's great that it works, but I'd like to know how and why the message box functionality defined in CloseEvent
method is called within the keyPressEvent
method.
Full script follows:
import sys
from PyQt5.QtWidgets import (
QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
from PyQt5.QtCore import QCoreApplication, Qt
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn = QPushButton("Close", self)
btn.setToolTip("Close Application")
# btn.clicked.connect(QCoreApplication.instance().quit)
# instead of above button signal, try to call closeEvent method below
btn.clicked.connect(self.closeEvent)
btn.resize(btn.sizeHint())
btn.move(410, 118)
self.setGeometry(30, 450, 500, 150)
self.setWindowTitle("Terminator")
self.show()
def closeEvent(self, event):
"""Generate 'question' dialog on clicking 'X' button in title bar.
Reimplement the closeEvent() event handler to include a 'Question'
dialog with options on how to proceed - Save, Close, Cancel buttons
"""
reply = QMessageBox.question(
self, "Message",
"Are you sure you want to quit? Any unsaved work will be lost.",
QMessageBox.Save | QMessageBox.Close | QMessageBox.Cancel,
QMessageBox.Save)
if reply == QMessageBox.Close:
event.accept()
else:
event.ignore()
def keyPressEvent(self, event):
"""Close application from escape key.
results in QMessageBox dialog from closeEvent, good but how/why?
"""
if event.key() == Qt.Key_Escape:
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())
Hope someone can take the time to enlighten me.
Your second question answers the first question.
The reimplemented keyPressEvent
method calls close()
, which sends a QCloseEvent
to the widget. Subsequently, the widget's closeEvent
will be called with that event as its argument.
So you just need to connect the button to the widget's close()
slot, and everything will work as expected:
btn.clicked.connect(self.close)