Qt 调用setLayout后,父对象自动设置
1、先来看一个简单的Qt程序,代码如下:
LabelEx.h
#ifndef LABELEX_H
#define LABELEX_H#include <qlabel.h>// 简单重写QLabel类
class LabelEx : public QLabel
{Q_OBJECT
public:explicit LabelEx(QWidget *parent = nullptr);~LabelEx();signals:
};#endif // LABELEX_H
LabelEx.cpp
#include "LabelEx.h"
#include <qdebug.h>LabelEx::LabelEx(QWidget *parent): QLabel{parent}
{}LabelEx::~LabelEx()
{qDebug() << "LabelEx destructor";
}
测试对话框:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "LabelEx.h"class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();private:void init();private:LabelEx *m_lbInfo = nullptr;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <qboxlayout.h>
#include <qdebug.h>Dialog::Dialog(QWidget *parent): QDialog(parent)
{init();
}Dialog::~Dialog() {}void Dialog::init()
{setMinimumSize(200, 200);m_lbInfo = new LabelEx(); // 无父对象m_lbInfo->setText("测试1");QHBoxLayout *hLay = new QHBoxLayout(); // 无父对象hLay->addWidget(m_lbInfo);if (m_lbInfo->parent() == hLay) {qDebug() << "m_lbInfo->parent() == hLay";}if (m_lbInfo->parent() == this) {qDebug() << "m_lbInfo->parent() == this";}if (m_lbInfo->parent() == nullptr) {qDebug() << "m_lbInfo->parent() == nullptr";}if (hLay->parent() == this) {qDebug() << "hLay->parent() == this";}if (hLay->parent() == nullptr) {qDebug() << "hLay->parent() == nullptr";}
}
运行后可以看到打印信息:
m_lbInfo->parent() == nullptr
hLay->parent() == nullptr
关闭对话框后,m_lbInfo没有调用析构函数,与hLay都存在内存泄漏的风险(因为没有父对象,不会自动释放资源)
修改Dialog::init()后:
void Dialog::init()
{setMinimumSize(200, 200);m_lbInfo = new LabelEx(); // 无父对象m_lbInfo->setText("测试1");QHBoxLayout *hLay = new QHBoxLayout(); // 无父对象hLay->addWidget(m_lbInfo);this->setLayout(hLay);if (m_lbInfo->parent() == hLay) {qDebug() << "m_lbInfo->parent() == hLay";}if (m_lbInfo->parent() == this) {qDebug() << "m_lbInfo->parent() == this";}if (m_lbInfo->parent() == nullptr) {qDebug() << "m_lbInfo->parent() == nullptr";}if (hLay->parent() == this) {qDebug() << "hLay->parent() == this";}if (hLay->parent() == nullptr) {qDebug() << "hLay->parent() == nullptr";}
}
其实只是增加一行代码:this->setLayout(hLay)
可以看出打印信息:
m_lbInfo->parent() == this
hLay->parent() == this
由此可见,QWidget对象在调用setLayout(QLayout *lay)后,会把lay和lay布局中的QWidget对象都设为自身的子对象。
关闭对话框后,打印信息:LabelEx destructor
m_lbInfo调用了析构函数,自动释放了资源。
【题外话】QObject对象在释放资源时,会自动释放它子对象的资源,相信大家都明白,因为QObject有一个QObjectList类型的对象,专门管理子对象,包括释放自身资源前会遍历释放子对象资源。
2、扩展
修改Dialog类
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "LabelEx.h"class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();private:void init();private:QWidget *m_wgt = nullptr;LabelEx *m_lbInfo = nullptr;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <qboxlayout.h>
#include <qdebug.h>Dialog::Dialog(QWidget *parent): QDialog(parent)
{init();
}Dialog::~Dialog() {}void Dialog::init()
{setMinimumSize(600, 200);m_wgt = new QWidget(); // 无父对象m_lbInfo = new LabelEx(m_wgt); // 父对象为m_wgtm_lbInfo->setText("测试1:");QHBoxLayout *hLay = new QHBoxLayout();hLay->addWidget(m_lbInfo);m_wgt->setLayout(hLay);QVBoxLayout *vLay = new QVBoxLayout();vLay->addWidget(m_wgt);this->setLayout(vLay);if (m_lbInfo->parent() == m_wgt){qDebug() << "m_lbInfo->parent() == m_wgt";}if (m_lbInfo->parent() == hLay) {qDebug() << "m_lbInfo->parent() == hLay";}if (m_lbInfo->parent() == this) {qDebug() << "m_lbInfo->parent() == this";}if (m_wgt->parent() == this) {qDebug() << "m_wgt->parent() == this";} else {qDebug() << "m_wgt->parent() != this";}if (hLay->parent() == m_wgt) {qDebug() << "hLay->parent() == m_wgt";}if (hLay->parent() == this) {qDebug() << "hLay->parent() == this";}if (vLay->parent() == this) {qDebug() << "vLay->parent() == this";} else {qDebug() << "vLay->parent() != this";}
}
运行程序后,打印信息如下:
m_lbInfo->parent() == m_wgt
m_wgt->parent() == this
hLay->parent() == m_wgt
vLay->parent() == this
【分析】由于m_wgt嵌入在vLay布局中,而vLay的父对象是this,因而m_wgt的父对象也变为this。由于调用了m_wgt->setLayout(hLay),因而hLay的父对象是m_wgt(注意不是this),m_lbInfo嵌入在hLay中,因此它的父对象也随hLay。
退出对话框后,打印信息:LabelEx destructor
m_lbInfo自动释放了资源(它毕竟属于Dialog的孙对象,在m_wgt释放对象前不会忘了它)