Qt: Como lidar com o evento do usuário pressionando o botão 'X' (fechar)?

126

Estou desenvolvendo um aplicativo usando o Qt. Não sei qual slot corresponde ao evento "o usuário clicar no botão 'X' (fechar) da moldura da janela", ou seja, este botão:

Botão Fechar da janela

Se não houver um slot para isso, alguém pode me sugerir algum outro método pelo qual eu possa iniciar uma função depois que o usuário pressionar o botão Fechar.

Shiva
fonte

Respostas:

169

Se você tiver um, QMainWindowpoderá substituir o closeEventmétodo.

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


Se você estiver subclassificando a QDialog, closeEventnão será chamado e, portanto, você deverá substituir 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
fonte
Se meu aplicativo for criado pela subclasse QApplication, como posso obter a mesma coisa que acima?
prakashpun
@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));deve funcionar. Veja a resposta de Sebastian abaixo.
Shiva
1
Você também pode usar o setAttribute(Qt::WA_QuitOnClose);MainWindow.
Borzh
Tem certeza de que a subclasse de QDialog não será chamada closeEvent? Funciona para mim, e a documentação de QCloseEvent diz que O manipulador de eventos QWidget :: closeEvent () recebe eventos de fechamento e QDialog também é um Widget, certo? Ou está relacionado à versão mais antiga do Qt (<5.x) de alguma forma?
Dimitri Podborski
1
@incBrain Mesmo no Qt 4.8, o botão 'X' chama closeEventum QDialog, mas se o usuário pressionar Esc no teclado, o QDialog é fechado sem chamar closeEvent.
Asclepix 31/03/16
16

Bem, eu entendi. Uma maneira é substituir o método na sua definição de classe e adicionar seu código nessa função. Exemplo: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
fonte
12

Você pode anexar um SLOT ao

void aboutToQuit();

sinal do seu QApplication. Este sinal deve ser aumentado logo antes do aplicativo ser fechado.

Sebastian Lange
fonte
2
Usamos o tipo de: #connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
Sebastian Lange
3
No entanto, cite a documentação : "Observe que nenhuma interação do usuário é possível neste estado".
Ignitor
10

você também pode reimplementar o membro protegido QWidget :: closeEvent ()

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