1

I have a parent-child window in my Qt application. Parent class is a QDialog named A and child class is QMainWindow named B. Now I want that whenever B is closed through the 'X' button a signal is to be emitted which can be caught by a slot in class A through which I want certain functionality to be implemented. Is there a predefined signal in Qt I can use?

I want something like this:

B *b=new B;
//some code
connect(b,SIGNAL(destroyed()),this,&A::doSomething);

B also has a QWidget which I can use to detect the destroyed signal. How do I implement this? Do I need to emit a custom signal from ~B() ?

Edit: I don't want to destroy the object b as this would require a reallocation when I want to recreate the window B from A and I want to keep the parameters of b.

Abhishek Agarwal
  • 1,190
  • 2
  • 19
  • 38
  • Possible duplicate of [Qt: How do I handle the event of the user pressing the 'X' (close) button?](https://stackoverflow.com/questions/17480984/qt-how-do-i-handle-the-event-of-the-user-pressing-the-x-close-button) – Thrawn Sep 25 '17 at 10:20

2 Answers2

2

Your solution would only work if you set a Qt::WA_DeleteOnClose attribute to your B widget:

b->setAttribute(Qt::WA_DeleteOnClose);

Another option would be to reimplement close event and emit a custom signal there.

thuga
  • 12,601
  • 42
  • 52
  • So there are no inbuilt signals that get emitted when a window gets destroyed? – Abhishek Agarwal Sep 25 '17 at 10:24
  • The line in my code gives me compilation errors when build – Abhishek Agarwal Sep 25 '17 at 10:25
  • You are mixing the new connect syntax with the old one. – thuga Sep 25 '17 at 10:28
  • `QObject::destroyed` is such signal. But by default, the widgets are not destroyed when you close them. That is why you need the `Qt::WA_DeleteOnClose` attribute. – thuga Sep 25 '17 at 10:34
  • So this will basically destroy the object `b`? Is there any way if I still want to keep the object b intact? – Abhishek Agarwal Sep 25 '17 at 10:47
  • Then you have to either [install an event filter](http://doc.qt.io/qt-5/eventsandfilters.html#event-filters) on your `b` widget, or reimplement `closeEvent`. – thuga Sep 25 '17 at 10:54
  • Thanks! I reimplemented the closeEvent and added a custom signal and it worked. Wish Qt also provided a closed signal along with destroyed for Qt Objects though. Also found this example that helped: http://doc.qt.io/qt-5/qtwidgets-mainwindows-application-example.html – Abhishek Agarwal Sep 26 '17 at 03:40
1

Connect your object like this:

widget = new QWidget();
//widget->show(); //optional using
connect(widget, &QWidget::destroyed, this, &MainWindow::widgetDestroy);
widget->setAttribute(Qt::WA_DeleteOnClose);

.cpp :

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButtonNew_clicked()
{
    widget = new QWidget();
    widget->show();
    connect(widget, &QWidget::destroyed, this, &MainWindow::widgetDestroy);
    widget->setAttribute(Qt::WA_DeleteOnClose);
}

void MainWindow::on_pushButtonDel_clicked()
{
    delete widget;
}

void MainWindow::widgetDestroy()
{
    qDebug()<< "deleted."; //after destroy widget this function calling.
}

.h :

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWidget>
#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private slots:

    void widgetDestroy();

    void on_pushButtonNew_clicked();

    void on_pushButtonDel_clicked();

private:
    Ui::MainWindow *ui;
    QWidget *widget;
};

#endif // MAINWINDOW_H

.ui :

enter image description here

Farhad
  • 4,119
  • 8
  • 43
  • 66
  • @AbhishekAgarwal Download Sample app here: https://www.mediafire.com/file/7f0434k0qdsv1pz/DestroyWidget.rar – Farhad Sep 25 '17 at 10:31
  • this works after adding the `setAttribute` command given in the answer by @thuga. Please add this to the answer. – Abhishek Agarwal Sep 25 '17 at 10:46
  • @AbhishekAgarwal I just test it, it's working without `setAttribute` i delete it with line `delete widget;` – Farhad Sep 25 '17 at 10:49
  • I tested it in my system as well it was working with your application. But it wasnt emitting the signal with my application. Maybe Qt version could be the issue? I am on Qt 5.9 – Abhishek Agarwal Sep 25 '17 at 10:50
  • It's weird, i am also Qt 5.9.0 – Farhad Sep 25 '17 at 10:52
  • Tested it again with and without the attribute. Same thing. Version is same for both applications. I dont know whats the issue here. – Abhishek Agarwal Sep 25 '17 at 10:57
  • Okay I found out the issue. That `setAttribute` statement is required. I was checking with the del button you have provided yesterday. When I close from the X button of the newly formed widget, the destroyed signal is not emitted i.e. the 'deleted' is not printed in console. – Abhishek Agarwal Sep 26 '17 at 03:26
  • @AbhishekAgarwal I test it, your right i update my answer. but you should remember that there is big difference between closing widget and deleting it. thanks for your feedback. – Farhad Sep 26 '17 at 04:34
  • yeah I get the difference now. Since destroyed was the only signal provided by Qt for this, I guess I went along with that without considering other options. – Abhishek Agarwal Sep 26 '17 at 04:40