QBoxLayout的所有者是否成为所有布局小部件的所有者?

20

我正在查看这里的示例,想知道它是否存在内存泄漏。我已经阅读了有关主题的文章mem leak on delete。然而,虽然QWidgets确实保留了添加到其中的小部件的所有权,但是布局却没有。

从QT代码中可以看出,具有布局的父项会获得该布局中所有小部件的所有权。但是,我在文档中没有看到任何此方面的参考。

Window::Window()
{
 editor = new QTextEdit();
 QPushButton *sendButton = new QPushButton(tr("&Send message"));

 connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage()));

 QHBoxLayout *buttonLayout = new QHBoxLayout();
 buttonLayout->addStretch();
 buttonLayout->addWidget(sendButton);
 buttonLayout->addStretch();

 QVBoxLayout *layout = new QVBoxLayout(this);
 layout->addWidget(editor);
 layout->addLayout(buttonLayout);

 setWindowTitle(tr("Custom Type Sending"));
}

虽然派生类没有提到,但基本布局类(QLayout)表示addWidget调用addItem...而addItem则表明:“ 注意: 项目的所有权已转移到布局,并且布局有责任删除它。”http://doc.qt.nokia.com/4.7-snapshot/qlayout.html#addItem - HostileFork says dont trust SE
@HostileFork,item 的所有权被转移到布局上。而不是小部件本身的所有权。请参阅我的答案,试图澄清这一点。 - Boris Dalstein
3个回答

31

来自布局管理

使用布局的技巧

当您使用布局时,构建子窗口部件时无需传递父窗口。 布局会自动重新分配窗口部件的父窗口(使用QWidget::setParent()),使它们成为安装了该布局的窗口控件的子项。

注意:在布局中的窗口部件是安装了该布局的窗口控件的子项,而不是布局本身的子项。窗口小部件只能拥有其他窗口小部件作为父项,而不能拥有布局。

您可以使用布局上的addLayout()嵌套布局;然后该内部布局成为插入到的布局的子项。


2
没有寻求这个。谢谢您的回答。 - Anton
另外需要注意的是,“所有权”归属于布局,而父级分配是针对布局的父部件进行的:http://doc.trolltech.com/4.7/qlayout.html#addItem - jdi
@jdi,item的所有权被转移到布局中。而不是小部件本身的所有权。请参阅我的答案,试图澄清这一点。QWidget的所有者(在内存管理意义上)始终是其父小部件,因此不能是布局。 - Boris Dalstein

4
不,QLayouts不会接管管理的QWidgets。
下面是addWidget()的实现代码:
void QLayout::addWidget(QWidget *w)
{
    addChildWidget(w);
    addItem(QLayoutPrivate::createWidgetItem(this, w));
}

解释:

  1. addChildWidget() 简单确保被管理的 widget w 从其他布局中移除。

  2. createWidgetItem(this, w) 分配一个新的 QWidgetItem,该 QWidgetItem 存储指向 w 的指针,但是 不负责拥有 w

  3. addItem() 将该项添加到布局中,并拥有 QWidgetItem(而非由 QWidgetItem 观察的 QWidget 的所有权)。这意味着当 QLayout 被销毁时,QWidgetItem 也将被销毁。然而,QWidget w 仍然没有被销毁。

当其父 QWidget 被销毁时,QWidget 将会被销毁。当 parent->setLayout(layout) 被调用时,QLayout 会自动分配该父组件。


0

我不确定2016年时的情况,但现在(Qt 5.15...)布局明确设置了父级...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接