P: Jak mam obsłużyć zdarzenie użytkownika naciskając przycisk „X” (zamknij)?

126

Tworzę aplikację przy użyciu Qt. Nie wiem, który slot odpowiada zdarzeniu „kliknięcia przez użytkownika przycisku 'X' (zamknij) ramy okna”, czyli tego przycisku:

Przycisk zamykania okna

Jeśli nie ma na to miejsca, czy ktoś może zasugerować mi inną metodę, dzięki której mogę uruchomić funkcję po naciśnięciu przez użytkownika przycisku zamykającego.

siedmiodniowa żałoba
źródło

Odpowiedzi:

169

Jeśli masz metodę, QMainWindowmożesz ją zastąpić 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();
    }
}


Jeśli tworzysz podklasę a QDialog, closeEventnie zostanie wywołana, więc musisz nadpisać 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
źródło
Jeśli moja aplikacja została utworzona przez podklasę QApplication, jak mogę osiągnąć to samo, co powyżej?
prakashpun
@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));powinno działać. Zobacz odpowiedź Sebastiana poniżej.
Shiva,
1
Możesz również chcieć użyć setAttribute(Qt::WA_QuitOnClose);dla MainWindow.
Borzh
Czy jesteś pewien, że podklasa QDialog nie wywoła closeEvent? To działa dla mnie, a dokumentacja QCloseEvent mówi, że program obsługi zdarzeń QWidget :: closeEvent () odbiera zdarzenia zamknięcia, a QDialog jest również widżetem, prawda? Czy jest to w jakiś sposób powiązane ze starszą wersją Qt (<5.x)?
Dimitri Podborski
1
@incBrain Nawet w Qt 4.8 przycisk „X” wywołuje closeEventQDialog, ale jeśli użytkownik naciśnie Esc na klawiaturze, QDialog zostanie zamknięty bez wywołania closeEvent.
asclepix
16

Cóż, rozumiem. Jednym ze sposobów jest zastąpienie metody w definicji klasy i dodanie kodu do tej funkcji. Przykład:QWidget::closeEvent(QCloseEvent *event)

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


void foo::closeEvent(QCloseEvent *bar)
{
    // Do something
    bar->accept();
}
siedmiodniowa żałoba
źródło
12

Możesz dołączyć SLOT do

void aboutToQuit();

sygnał twojego QApplication. Ten sygnał powinien zostać podniesiony tuż przed zamknięciem aplikacji.

Sebastian Lange
źródło
2
Użyliśmy tego w pewnym sensie:connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
Sebastian Lange,
3
Cytuj jednak z dokumentacji : „Zwróć uwagę, że w tym stanie nie jest możliwa żadna interakcja użytkownika”.
Ignitor,
10

również możesz ponownie zaimplementować chroniony element członkowski QWidget :: closeEvent ()

void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
    // do what you need here
    // then call parent's procedure
    QWidget::closeEvent(event);
}
Alexander
źródło