Qt 创建的窗口一闪而过
- 引言
- 一、详细的解决方案 - 附代码
- 二、参考博文
引言
创建的窗口一闪而过,就是创建完立马被销毁了,常见情况是在一个函数中创建窗口并show() - 即创建在了栈上,函数结束局部变量(窗口)自动被释放
。主流的解决方法有两种:
-
- 使用指针
new一个窗口
,函数结束也不会被释放,但是容易造成内存泄露,需记得释放内存
- 使用指针
-
- 使用
loop.exec();
进行阻塞,容易造成死循环,需记得退出事件循环loop
- 使用
大多数博文讲述的比较简单,能解决问题,但是有一定的隐患 (内存泄露)。还有一种解决方案:变成父类窗体的一个成员变量。但是既然都在函数中创建了,显然是不想让其占用内存. 用完即销毁 故这种方法在本文情况下不推荐.
一、详细的解决方案 - 附代码
首先介绍一个继承QWidget的自定义窗口类 - Form
,之后会用到
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr);
~Form();
signals:
void closed();
private:
Ui::Form *ui;
protected:
void closeEvent(QCloseEvent *event) override;
};
void Form::closeEvent(QCloseEvent *event)
{
emit closed();
}
-
- 使用指针
new一个窗口
,设置Qt::WA_DeleteOnClose
关闭即销毁,而不是隐藏
- 使用指针
Form *w = new Form();
w->setAttribute(Qt::WA_DeleteOnClose);
w->show();
-
- 使用
loop.exec();
进行阻塞,其退出绑定窗体的关闭信号 (QWidget无关闭信号,需自定义一个
)
- 使用
Form w;
w.show();
QEventLoop loop;
connect(&w, &Form::closed, &loop, &QEventLoop::quit);
loop.exec();
qDebug() << "exec";
关于验证,在Windows可打开任务管理器查看内存变化 (Linux下可使用top命令),代码释放内存后,很快就会看到内存减小,如下图所示 (
关注左侧 Form窗口的弹出和关闭,以及右侧QtMemoryDemo程序的内存占用大小 21.7MB 和 22.2MB
)
测试代码如下,定时器5秒弹一个窗口,且窗口们相互独立 - 即可多个弹出窗口并存,全部关闭后内存波动明显 (QEventLoop是阻塞式的,使用以下定时器的方式只能弹出一个窗口
):
this->timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, []{
qDebug() << "timeout";
Form *w = new Form();
w->setAttribute(Qt::WA_DeleteOnClose);
w->show();
});
timer->setInterval(5000);
timer->start();
二、参考博文
QEventLoop使用的坑:https://blog.csdn.net/baidu_31541363/article/details/126430052
一个使用QEventLoop时,遇到的教训:https://blog.csdn.net/u010168781/article/details/86659967/
内存泄漏与堆溢出检测工具一览:https://blog.csdn.net/qq_21438461/article/details/133215065
C++程序在Windows任务管理器中内存占用不降:https://blog.csdn.net/just0kk/article/details/53914634
为什么我delete后内存没有被释放?:https://blog.csdn.net/beMyBest/article/details/48771433
为什么我delete一个Widget,内存不会释放呢:http://www.qtcn.org/bbs/read-htm-tid-46872.html