Qt: Comment gérer l'événement de l'utilisateur appuyant sur le bouton «X» (fermer)?

126

Je développe une application utilisant Qt. Je ne sais pas quel slot correspond à l'événement "l'utilisateur clique sur le bouton 'X' (fermer) du cadre de la fenêtre" c'est à dire ce bouton:

Bouton de fermeture de la fenêtre

S'il n'y a pas de slot pour cela, quelqu'un peut-il me suggérer une autre méthode par laquelle je peux démarrer une fonction après que l'utilisateur a appuyé sur ce bouton de fermeture.

Shiva
la source

Réponses:

169

Si vous avez une méthode, QMainWindowvous pouvez remplacer 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();
    }
}


Si vous sous-classez a QDialog, le closeEventne sera pas appelé et vous devez donc remplacer 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();
    }
}
asclépix
la source
Si mon application est créée en sous-classant QApplication, comment puis-je réaliser la même chose que ci-dessus?
prakashpun
@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));devrait fonctionner. Voir la réponse de Sebastian ci-dessous.
Shiva
1
Vous pouvez également utiliser setAttribute(Qt::WA_QuitOnClose);pour MainWindow.
Borzh
Êtes-vous sûr que la sous-classification de QDialog n'appellera pas closeEvent? Cela fonctionne pour moi, et la documentation de QCloseEvent dit que le gestionnaire d'événements QWidget :: closeEvent () reçoit des événements de fermeture et QDialog est également un widget, non? Ou est-ce lié à l'ancienne version de Qt (<5.x) d'une manière ou d'une autre?
Dimitri Podbourski
1
@incBrain Même dans Qt 4.8, le bouton 'X' appelle closeEventun QDialog, mais si l'utilisateur appuie sur Echap sur le clavier, le QDialog se ferme sans appeler closeEvent.
asclepix
16

Eh bien, je l'ai. Une façon est de remplacer la méthode dans votre définition de classe et d'ajouter votre code dans cette fonction. Exemple:QWidget::closeEvent(QCloseEvent *event)

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


void foo::closeEvent(QCloseEvent *bar)
{
    // Do something
    bar->accept();
}
Shiva
la source
12

Vous pouvez attacher un SLOT au

void aboutToQuit();

signal de votre QApplication. Ce signal doit être émis juste avant la fermeture de l'application.

Sébastien Lange
la source
2
Nous l'avons utilisé en quelque sorte:connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
Sebastian Lange
3
Cependant, citez la documentation : "Notez qu'aucune interaction utilisateur n'est possible dans cet état."
Ignitor
10

vous pouvez également réimplémenter le membre protégé QWidget :: closeEvent ()

void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
    // do what you need here
    // then call parent's procedure
    QWidget::closeEvent(event);
}
Alexandre
la source