现在的位置: 首页 > 生活点滴 > 正文

Qt窗口关闭和应用程序停止是否调用析构函数的一些说明(转)

2018年07月27日 生活点滴 ⁄ 共 2244字 ⁄ 字号 Qt窗口关闭和应用程序停止是否调用析构函数的一些说明(转)已关闭评论 ⁄ 阅读 144 次

在main,栈上面创建一个窗口A,关闭窗口A时,会调用析构函数。 如果在这个窗口A的构造函数中再创建一个窗口B,并且在A的析构函数中对B进行释放。

第一种形式:

MainWindow * b = new MainWindow();

当关闭窗口A,再关闭窗口B时,创建B的析构函数被调用,窗口A的析构函数被调用 (这种关闭方式有明显的卡顿,当关闭A,按照规则,B应该被关掉,释放,但是B窗口还显示在桌面,多次运行,发现还会存在A析构不执行的问题(析构中的打印语句并未被打印在控制台),所以这种方式存在问题)

反过来,当先关闭窗口B,再关闭窗口A,B的析构函数被调用,窗口A的析构函数被调用 (这种关闭方式无卡顿,实际上是B窗口被隐藏,并未主动执行析构,而在A的析构函数中被动执行,这也是为什么关闭B时,显示并未调用B析构,而关闭A时,才显示调用B析构的原因)

我们给窗口B添加Qt::WA_DeleteOnClose试一下(构造函数中添加setAttribute(Qt::WA_DeleteOnClose)),因为窗口B是窗口在堆上的,可以使用setAttribute(Qt::WA_DeleteOnClose)),

还是先关闭窗口A,再关闭窗口B,显示调用了窗口B的析构函数,然后出现异常,这个异常应该是重复析构B发送的异常。

把窗口A中关于窗口B释放的代码去掉,显示调用了窗口B的析构函数,调用窗口A的析构函数,但是没有出现异常(存在卡顿,多次运行,发现还会存在A析构不执行的问题(析构中的打印语句并未被打印在控制台))。

现在反过来,先关闭窗口B,由于窗口B设置了setAttribute(Qt::WA_DeleteOnClose))属性,立即执行了析构函数,接着关闭窗口A,如果不出意外的话,应该会出现异常,因为窗口B已经被释放,再在窗口A中再次释放B会报异常,把A中析构函数中的释放B的代码再次注释,运行,显示依次调用了窗口B的析构函数,窗口A的析构函数(无卡顿)。

两个窗口联动时设置方式:

情景如下:

在main中,栈上面创建一个窗口A,在这个窗口A的构造函数中再创建一个窗口B(不指定发对象,两个窗口独立显示)。

A作为启动界面,比如延时2S自动启动B,然后A隐藏,不在显示。

退出操作,有两种方式:

1、在启动B之前,即A显示的那2S中时:

2、B启动完,A已经隐藏时:

此时需要设置:

一、不要给窗口B添加Qt::WA_DeleteOnClose

不要给窗口A添加Qt::WA_DeleteOnClose,A是在栈上申请,close会自动调用析构函数

二、在B的close事件中,给A发信号,由于B没有WA_DeleteOnClose属性,所以此时B只是隐藏了,并不会调用析构函数。

三、A的槽函数中,调用close()

四、在A的析构函数中delete B,此时B才被删除,调用析构函数

第二种形式,指定父窗口

MainWindow * b = new MainWindow(this);

A窗口析构没有写释放B窗口的代码情况下:

关闭A窗口(被释放),B窗口跟着关闭(被释放)(无卡顿)。

关闭B窗口(只是隐藏),关闭A窗口(被释放)(无卡顿)。

再次试着给 b 添加setAttribute(Qt::WA_DeleteOnClose))属性,关闭B窗口,执行B析构,再关闭A,执行A的析构(无卡顿)。

关闭A窗口,执行A的析构,执行B的析构,并且B窗口被关闭(无卡顿)。

这里是因为QT的父子对象机制在起作用,原因就在于那个this。

当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象,然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除,所以如果new出来的控件,如果有指定父对象,无需我们手动删除。

还有一个发现,就是其他控件如果指定A窗口作为父窗口,是会被嵌入在A窗口中的,但是MainWindow这个类的窗口不会被嵌入 反过来则不然。

但是上面这些仅仅是在基本情况下,当我把窗口属性设置为无边框,无任务栏之后等等不同属性之后,再次关闭窗口,析构函数不会被自动调用,换句话说就是只是窗口关闭了,但是应用程序本身还没有关闭,最明显的特征就是当你关闭了窗口,qt的应用程序输出窗口还是显示着红色的方块而不是绿色的三角。

这个时候可以在你想要关闭的地方添加下列代码,应用程序就会被关闭。

 QApplication* app;
    app->quit();

还有一种情况就是在MainWindow中创建widget窗口,但是一关闭最后一个widget,MainWindow就会被关闭,是不是不可思议,在没找到解决方案之前,我只能判断是不是最后一个widget,如果是我就隐藏,而不是关闭,举个例子。

例如qq 主界面是MainWindow 双击好友生成widget窗口。

当关闭这些widget窗口到最后一个的时候,主窗口会跟着关闭,出现这种症状的原因之一,是设置了窗口的属性

也就是使用了这个函数setWindowFlags(),一不做二不休,将这个widget窗口再添加一个属性setWindowFlag(Qt::CoverWindow);

这个问题可能会不存在了~

还有一个问题就是关闭窗口,可能会报程序异常结束,这个错误也和main中窗口创建的位置有关。

转自:https://cloud.tencent.com/developer/article/1836559

×