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

Якщо моя програма створена підкласифікацією QApplication, то як я можу досягти того самого, що описано вище?
пракашпун

@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));має працювати. Дивіться відповідь Себастьяна нижче.
Шива

1
Ви можете також використовувати setAttribute(Qt::WA_QuitOnClose);для MainWindow.
Борж

Ви впевнені, що підкласифікація QDialog не зателефонує closeEvent? Це працює для мене, і документація QCloseEvent говорить про те, що обробник подій QWidget :: closeEvent () отримує близькі події, а QDialog також є віджетом, чи не так? Або це якось пов’язано зі старшою версією Qt (<5.x)?
Димитрій Підборський

1
@incBrain Навіть у Qt 4.8 кнопка "X" дзвонить closeEventу QDialog, але якщо користувач натискає 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
Однак, цитуйте з документації : "Зауважте, що жодна взаємодія з користувачем у цьому стані неможлива".
Запалювач

10

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

void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
    // do what you need here
    // then call parent's procedure
    QWidget::closeEvent(event);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.