Qt: Как мне обработать событие, когда пользователь нажимает кнопку «X» (закрыть)?

126

Я разрабатываю приложение с использованием Qt. Я не знаю, какой слот соответствует событию «пользователь нажимает кнопку« X »(закрыть) в рамке окна», то есть этой кнопке:

Кнопка закрытия окна

Если для этого нет слота, может ли кто-нибудь предложить мне другой метод, с помощью которого я могу запустить функцию после того, как пользователь нажмет кнопку закрытия.

Шива
источник

Ответы:

169

Если у вас есть метод, который QMainWindowвы можете переопределить closeEvent.

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


Если вы создаете подкласс a QDialog, closeEventон не будет вызываться, поэтому вам нужно переопределить 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();
    }
}
asclepix
источник
Если мое приложение создано путем создания подкласса от QApplication, как я могу добиться того же, что указано выше?
пракашпун 07
@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));должен работать. См. Ответ Себастьяна ниже.
Шива
1
Вы можете также использовать setAttribute(Qt::WA_QuitOnClose);для MainWindow.
Borzh
Вы уверены, что наследование QDialog не вызовет closeEvent? У меня это работает, и в документации QCloseEvent сказано, что обработчик событий QWidget :: closeEvent () получает события закрытия, а QDialog также является виджетом, верно? Или это как-то связано со старой версией Qt (<5.x)?
Dimitri Podborki
1
@incBrain Даже в Qt 4.8 кнопка 'X' вызывает closeEventQDialog, но если пользователь нажимает Esc на клавиатуре, QDialog закрывается без вызова closeEvent.
asclepix
16

Хорошо, я понял. Один из способов - переопределить метод в определении вашего класса и добавить код в эту функцию. Пример:QWidget::closeEvent(QCloseEvent *event)

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


void foo::closeEvent(QCloseEvent *bar)
{
    // Do something
    bar->accept();
}
Шива
источник
12

Вы можете прикрепить СЛОТ к

void aboutToQuit();

сигнал вашего QApplication. Этот сигнал должен быть подан непосредственно перед закрытием приложения.

Себастьян Ланге
источник
2
Мы использовали это как бы:connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
Себастьян Ланге
3
Однако процитируем документацию : «Обратите внимание, что в этом состоянии взаимодействие с пользователем невозможно».
Ignitor
10

также вы можете повторно реализовать защищенный член QWidget :: closeEvent ()

void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
    // do what you need here
    // then call parent's procedure
    QWidget::closeEvent(event);
}
Александр
источник