ChatGPT解决这个技术问题 Extra ChatGPT

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

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:

https://i.stack.imgur.com/rgFqm.png

If there isn't a slot for this, is there any other way to trigger a function after the user presses the close button?


J
Jason Sundram

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

If my application is created by subclassing QApplication, then how can I achieve the same thing as above ?
@pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp())); should work. See Sebastian's answer below.
You may want to also use setAttribute(Qt::WA_QuitOnClose); for MainWindow.
Are you sure that subclassing QDialog will not call closeEvent? It works for me, and the documentation of QCloseEvent 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?
@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.
w
waldyrious

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

S
Sebastian Lange

You can attach a SLOT to the

void aboutToQuit();

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


We used it kind of: connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
However, quote from the documentation: "Note that no user interaction is possible in this state."
A
Alexander

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);
}