Qt 创建的窗口一闪而过【已解决】

引言

创建的窗口一闪而过,就是创建完立马被销毁了,常见情况是在一个函数中创建窗口并show() - 即创建在了栈上,函数结束局部变量(窗口)自动被释放。主流的解决方法有两种:

    1. 使用指针 new一个窗口,函数结束也不会被释放,但是容易造成内存泄露,需记得释放内存
    1. 使用 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();
}
    1. 使用指针 new一个窗口,设置Qt::WA_DeleteOnClose 关闭即销毁,而不是隐藏
        Form *w = new Form();
        w->setAttribute(Qt::WA_DeleteOnClose);
        w->show();
    1. 使用 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

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果你在Qt创建了一个子窗口,但它只是一闪而过并且很快消失,通常有两个常见的原因: 1. 对象作用域问题:子窗口对象的作用域可能仅限于一个函数或局部范围内。当该函数或范围结束时,子窗口对象将被销毁,导致窗口一闪而过。为了解决这个问题,你需要将子窗口对象声明为类的成员变量,以确保它的生命周期足够长,直到不再需要。 2. 窗口显示问题:子窗口可能没有正确显示。在创建窗口对象后,你需要调用 `show()` 方法来显示它。如果你忘记调用 `show()`,则子窗口将无法显示。 下面是一个示例,展示如何创建并显示一个子窗口: ```cpp #include <QApplication> #include <QMainWindow> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow mainWindow; mainWindow.setWindowTitle("Main Window"); QMainWindow childWindow; childWindow.setWindowTitle("Child Window"); childWindow.show(); // 显示子窗口 mainWindow.show(); // 显示主窗口 return a.exec(); } ``` 在这个示例中,我们创建了一个名为 `childWindow` 的子窗口对象,并调用 `show()` 方法来显示它。然后,我们创建了一个名为 `mainWindow` 的主窗口对象,并将子窗口作为其子窗口进行显示。最后,我们调用 `show()` 方法来显示主窗口。 确保在你的代码中正确处理子窗口的对象作用域和显示问题,以确保子窗口能够正常显示并保持可见。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大米粥哥哥

感谢认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值