PDA

View Full Version : entering and leaving a new event loop will not perform the deferred deletion ?



govi1
3rd February 2012, 13:51
Hi All,

In QT document of deleteLater ,it said:

Note that entering and leaving a new event loop (e.g., by opening a modal dialog) will not perform the deferred deletion; for the object to be deleted, the control must return to the event loop from which deleteLater() was called.

I am not quite understand what it means, there is an article http://agateau.wordpress.com/2010/09...ctdeletelater/
,but it is still confusing me .

could somebody give me an example for this ?

Thanks

wysota
3rd February 2012, 14:52
The event loop counts "levels" of nesting. When you call exec() on the application object in your main, the level is "1". When you open a modal dialog with a call to QDialog::exec() the level rises to "2". If you open another modal dialog from this one, the level will rise to "3". When you close the dialog it will fall back to "2". If you're on level "2" and you call deleteLater() on some object and then you open the dialog which causes the level to rise, you can't be certain that this dialog will not want to interact with the object you want deleted hence you can't delete it just yet so Qt defers deleting that object until the level drops back to "2".

govi1
3rd February 2012, 16:33
Great! That is the best answer I have found !!,Thank you very much :)))

I write a test program for it:



#include <QApplication>
#include <QString>
#include <QTimer>
#include <QDebug>
#include <QMetaObject>
#include <QThread>
#include <QDialog>

class Object : public QObject
{
Q_OBJECT
public:
Object(){qDebug()<<"** Object contruct **";}
~Object(){qDebug()<<"** Object destruct **";}
};

class DialogLevel3 : public QDialog
{
Q_OBJECT
public:
DialogLevel3():QDialog(){
setWindowTitle("DialogLevel3");
QTimer::singleShot(1000, this, SLOT(f()));
}
public slots:
void f(){
qDebug()<<"[ DialogLevel3"<<QThread::currentThread() <<" ]";
}
};


class DialogLevel2 : public QDialog
{
Q_OBJECT
public:
DialogLevel2():QDialog(){
setWindowTitle("DialogLevel2");
}
public slots:
void init(){
object = new Object;
qDebug()<<"starting eventloop level2";
QTimer::singleShot(1000, this, SLOT(f()));
exec();
qDebug()<<"return to level1";
}
void f(){
qDebug()<<"[ DialogLevel2"<<QThread::currentThread()<<" ]";
qDebug()<<"call object->deleteLater";
object->deleteLater();
DialogLevel3 dlg2;
qDebug()<<"starting eventloop level3";
dlg2.exec();
qDebug()<<"return to level2";
}
private:
Object *object;
};




int main(int argc,char* argv[])
{
QApplication app(argc, argv);
qDebug()<<"[ mainthread"<<QThread::currentThread()<<" ]";
DialogLevel2 dlg1;
QMetaObject::invokeMethod(&dlg1, "init",Qt::QueuedConnection);
qDebug()<<"starting eventloop level1";
app.exec();
}

#include "main.moc"