How do I handle the event of the user pressing the 'X' (close) button?

161.8k Views Asked by At

In Qt, what is the slot that 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, is there any other way to trigger a function after the user presses the close button?

6

There are 6 best solutions below

5
asclepix On BEST ANSWER

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();
    }
}
0
Shravan On

One way is to override the QWidget::closeEvent(QCloseEvent *) 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();
}
3
Sebastian Lange On

You can attach a SLOT to the

void aboutToQuit();

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

0
Alexander On

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);
}
0
A.R.M On

To capture the event of the close button being pressed without deriving from QWidget and the sort, you could use an event filter.

Here's a simple demonstration, using a simple application that displays a QWidget:

If you use the QWidget itself, you need to capture QEvent::Close:

#include "myEventFilter.h"
#include <QApplication>
#include <QWidget>

int main(int argc,char*argv[])
{
    QApplication a(argc, argv);
    
    w.installEventFilter(filter);
    
    QWidget *w = new QWidget();

    //install the event filter on the widget
    w->installEventFilter(filter);

    w->show();

    return a.exec();
}

Event filter:

#ifndef MYEVENTFILTER_H
#define MYEVENTFILTER_H

#include <QObject>
#include <QDebug>
#include <QEvent>

class myEventFilter : public QObject
{
    Q_OBJECT

public:
    myEventFilter (QObject *parent = nullptr) {}

protected:
    bool eventFilter(QObject * obj, QEvent * event) override
    {
        if (event->type() == QEvent::Close)
        {
            //handle the event here
            qDebug()<<"out";
           //In case you need the QWidget itself 
           QWidget *w = static_cast<QWidget*>(obj);
        }

        return QObject::eventFilter(obj, event);
    }
};

#endif // MYEVENTFILTER_H

If you use QApplication's object, you need to capture QEvent::Quit:

#include <QApplication>
#include "myEventFilter.h"

int main(int argc,char*argv[])
{
    QApplication a(argc, argv);

    QWidget *w = new QWidget();

    myEventFilter *filter = new myEventFilter();

    //install the event filter on QApplication object
    a.installEventFilter(filter);

    w->show();

    return a.exec();
}

Event filter

#ifndef MYEVENTFILTER_H
#define MYEVENTFILTER_H

#include <QObject>
#include <QDebug>
#include <QEvent>
#include <QLineEdit>

class myEventFilter : public QObject
{
    Q_OBJECT

public:
    myEventFilter (QObject *parent = nullptr) {}

protected:
    bool eventFilter(QObject * obj, QEvent * event) override
    {
        if (event->type() == QEvent::Quit)
        {
            //handle the event here as well
            qDebug()<<"out";
        }

        return QObject::eventFilter(obj, event);
    }
};

#endif // MYEVENTFILTER_H

0
Shaiful Islam On

The simple way to close properly using QCloseEvent.

void MainWindow::closeEvent (QCloseEvent *)
{
    QCoreApplication::quit();
}