136

I am developing an application using Qt. I don't know which slot corresponds to the event of "the user clicking the 'X'(close) button of the window frame" i.e. this button:

Close button of the window

If there isn't a slot for this, can anyone suggest me some other method by which I can start a function after the user presses that close button.

Andreas Haferburg
  • 4,678
  • 1
  • 29
  • 52
Shiva
  • 2,487
  • 2
  • 15
  • 34

4 Answers4

182

If you have a QMainWindow you can override closeEvent method.

#include <QCloseEvent>
void MainWindow::closeEvent (QCloseEvent *event)
{
    QMessageBox::StandardButton resBtn = QMessageBox::question( this, APP_NAME,
                                                                tr("Are you sure?\n"),
                                                                QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                                                                QMessageBox::Yes);
    if (resBtn != QMessageBox::Yes) {
        event->ignore();
    } else {
        event->accept();
    }
}


If you're subclassing a QDialog, the closeEvent will not be called and so you have to override reject():

void MyDialog::reject()
{
    QMessageBox::StandardButton resBtn = QMessageBox::Yes;
    if (changes) {
        resBtn = QMessageBox::question( this, APP_NAME,
                                        tr("Are you sure?\n"),
                                        QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                                        QMessageBox::Yes);
    }
    if (resBtn == QMessageBox::Yes) {
        QDialog::reject();
    }
}
Jason Sundram
  • 10,998
  • 19
  • 67
  • 84
asclepix
  • 7,653
  • 3
  • 28
  • 38
  • If my application is created by subclassing QApplication, then how can I achieve the same thing as above ? – prakashpun Jul 07 '15 at 05:47
  • @pra16 `connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));` should work. See Sebastian's answer below. – Shiva Jul 12 '15 at 09:21
  • 1
    You may want to also use `setAttribute(Qt::WA_QuitOnClose);` for MainWindow. – Borzh Nov 22 '15 at 17:14
  • Are you sure that subclassing QDialog will not call `closeEvent`? It works for me, and the documentation of [QCloseEvent](http://doc.qt.io/qt-5/qcloseevent.html) says that *The event handler QWidget::closeEvent() receives close events* and QDialog is also a Widget right? Or is it related to older Qt version (<5.x) somehow? – Dimitri Podborski Mar 30 '16 at 10:17
  • 1
    @incBrain Even in Qt 4.8 the 'X' button calls `closeEvent` in a QDialog, but if the user press _Esc_ on the keyboard the QDialog is closed without calling `closeEvent`. – asclepix Mar 31 '16 at 09:57
  • @asclepix thanks for clarification. So basically overwriting `reject` function would be the right move to solve this problem. I've found this sentence in the documentation: *In order to modify your dialog's close behavior, you can reimplement the functions accept(), reject() or done(). The `closeEvent()` function should only be reimplemented to preserve the dialog's position or to override the standard close or reject behavior* – Dimitri Podborski Mar 31 '16 at 10:25
  • Another way would be to connect to *rejected* signal of QDialog. – JeFf Mar 14 '18 at 14:42
  • @asclepix excellent answer!! – developer01 Feb 09 '21 at 19:19
16

Well, I got it. One way is to override the QWidget::closeEvent(QCloseEvent *event) method in your class definition and add your code into that function. Example:

class foo : public QMainWindow
{
    Q_OBJECT
private:
    void closeEvent(QCloseEvent *bar);
    // ...
};


void foo::closeEvent(QCloseEvent *bar)
{
    // Do something
    bar->accept();
}
waldyrious
  • 3,128
  • 4
  • 29
  • 35
Shiva
  • 2,487
  • 2
  • 15
  • 34
12

You can attach a SLOT to the

void aboutToQuit();

signal of your QApplication. This signal should be raised just before app closes.

Sebastian Lange
  • 3,715
  • 1
  • 15
  • 34
  • 3
    We used it kind of: ``connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));`` – Sebastian Lange Jul 10 '13 at 06:24
  • 3
    However, [quote from the documentation](http://doc.qt.io/qt-5/qcoreapplication.html#aboutToQuit): "Note that no user interaction is possible in this state." – Ignitor Dec 07 '15 at 11:02
10

also you can reimplement protected member QWidget::closeEvent()

void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
    // do what you need here
    // then call parent's procedure
    QWidget::closeEvent(event);
}
Alexander
  • 119
  • 1
  • 2