P: ¿Cómo manejo el evento de que el usuario presione el botón 'X' (cerrar)?

126

Estoy desarrollando una aplicación usando Qt. No sé qué ranura corresponde al evento de "que el usuario haga clic en el botón 'X' (cerrar) del marco de la ventana", es decir, este botón:

Botón de cierre de la ventana

Si no hay un espacio para esto, ¿alguien puede sugerirme algún otro método por el cual pueda iniciar una función después de que el usuario presione ese botón de cierre.

Shiva
fuente

Respuestas:

169

Si tiene un método QMainWindowpuede anular 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 está subclasificando a QDialog, closeEventno se llamará al, por lo que debe anular 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
fuente
Si mi aplicación se crea subclasificando QApplication, ¿cómo puedo lograr lo mismo que antes?
prakashpun
@ pra16 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));debería funcionar. Vea la respuesta de Sebastian a continuación.
Shiva
1
Es posible que desee utilizar también setAttribute(Qt::WA_QuitOnClose);para MainWindow.
Borzh
¿Estás seguro de que la subclase QDialog no llamará closeEvent? Funciona para mí, y la documentación de QCloseEvent dice que el controlador de eventos QWidget :: closeEvent () recibe eventos cercanos y QDialog también es un widget ¿no? ¿O está relacionado con la versión anterior de Qt (<5.x) de alguna manera?
Dimitri Podborski
1
@incBrain Incluso en Qt 4.8, el botón 'X' llama closeEventa un QDialog, pero si el usuario presiona Esc en el teclado, el QDialog se cierra sin llamar closeEvent.
asclepix
16

Bueno, lo tengo. Una forma es anular el método en su definición de clase y agregar su código a esa función. Ejemplo: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
fuente
12

Puede adjuntar un SLOT al

void aboutToQuit();

señal de su QApplication. Esta señal se debe generar justo antes de que se cierre la aplicación.

Sebastian Lange
fuente
2
Lo usamos como:connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp()));
Sebastian Lange
3
Sin embargo, cite la documentación : "Tenga en cuenta que no es posible la interacción del usuario en este estado".
Ignitor
10

También puede volver a implementar QWidget miembro protegido :: closeEvent ()

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