如何删除小部件上已经存在的布局?
Posted
技术标签:
【中文标题】如何删除小部件上已经存在的布局?【英文标题】:How to delete an already existing layout on a widget? 【发布时间】:2011-09-23 12:06:32 【问题描述】:您必须先删除现有的布局管理器(由 layout()) 在您可以使用新布局调用 setLayout() 之前。
来自http://doc.qt.io/qt-5.9/qwidget.html#setLayout
哪个函数用于删除之前的布局?
【问题讨论】:
【参考方案1】:Chris Wilson 的回答是正确的,但我发现布局不会删除其下方的子布局和 qwidgets。如果您有复杂的布局或可能存在内存泄漏,最好手动执行。
QLayout * layout = new QWhateverLayout();
// ... create complicated layout ...
// completely delete layout and sublayouts
QLayoutItem * item;
QLayout * sublayout;
QWidget * widget;
while ((item = layout->takeAt(0)))
if ((sublayout = item->layout()) != 0) /* do the same for sublayout*/
else if ((widget = item->widget()) != 0) widget->hide(); delete widget;
else delete item;
// then finally
delete layout;
【讨论】:
我认为这是不正确的,因为如果您在其构造函数中传递父级,它将删除子级和子布局。 您是否发现在删除之前隐藏小部件有什么好处,或者您只是想确定一下?我问是因为我使用删除而不隐藏,并且会对即将出现的副作用感兴趣【参考方案2】:你只是使用
delete layout;
就像使用 new
创建的任何其他指针一样。
【讨论】:
这会造成内存泄漏,请参阅 perden 的回答【参考方案3】:我想删除当前布局,将其替换为新布局,但保留由该布局管理的所有小部件。我发现在这种情况下,Chris Wilson 的解决方案效果不佳。布局并不总是改变。
这对我有用:
void RemoveLayout (QWidget* widget)
QLayout* layout = widget->layout ();
if (layout != 0)
QLayoutItem *item;
while ((item = layout->takeAt(0)) != 0)
layout->removeItem (item);
delete layout;
【讨论】:
你应该删除项目;在 layout->removeItem (item) 之后;否则您的程序中会出现内存泄漏。查看 perden 答案。【参考方案4】:此代码删除布局、其所有子级以及布局内的所有内容“消失”。
qDeleteAll(yourWidget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly));
delete layout();
这将删除小部件yourWidget
的所有直接小部件。使用Qt::FindDirectChildrenOnly
是必要的,因为它可以防止删除作为也在列表中的小部件的子小部件,并且可能已经被qDeleteAll
内的循环删除。
这里是qDeleteAll
的描述:
void qDeleteAll(ForwardIterator begin, ForwardIterator end)
使用 C++ 删除 > 运算符删除范围 [begin, end] 中的所有项目。项类型必须是指针类型(例如,QWidget *)。
请注意,qDeleteAll
需要使用来自该小部件(而不是布局)的容器调用。请注意,qDeleteAll
不会删除 yourWidget
- 只是它的子级。
现在可以设置新的布局了。
【讨论】:
这种方法的问题是你可能会不小心删除一些附加的QObject
到yourWidget
与布局/小部件结构无关,这个问题可能很难找到。
但是您可以过滤类型(在这种情况下为 QWidget*),并且您始终可以在找到子项后执行另一层过滤。我认为这是一个很好的解决方案以上是关于如何删除小部件上已经存在的布局?的主要内容,如果未能解决你的问题,请参考以下文章