关于在Qt 4中删除,删除小部件和布局

时间:2013-07-17 15:08:05

标签: qt layout widget qt4

(我使用Qt 4.7,Windows 7,64bit)。

我创建了一个自定义表。每行都是带有小部件的水平布局。 行保存在QList中以便于访问,孩子也是如此。这些行也会添加到父窗口小部件中。

如果我调整父窗口小部件的大小,我会计算新的尺寸,删除所有内容,然后重新创建它。

我的问题是我不想删除任何小部件。只有当我清理桌子时,我才会这样做。

由于我在QList内部和父布局内部有小部件,如何删除每一行中的所有小部件,删除所有布局,然后将它们添加到新布局?

如果我这样做:takeAt(0)为每个布局中的每个元素我有一个QLayoutItem,里面有一个小部件......如何在不删除小部件的情况下删除layoutItem?....如何删除小部件杀死它,无论是在父母还是孩子身上?因为有很多方法可以删除:removeItem,removeWidget ......在布局中,但不是takeWidget ...只是takeAt(),它给出了一个Qlayoutitem。

我尝试了几种方法,但无论发生什么事,我仍然会看到小部件。

有关此事的问题:

  • 小部件何时被删除?如果我从布局中取出窗口小部件(索引),它是否会被删除一段时间?如果我在另一个列表中有指向它的话会发生吗?

  • removeAt(index)是否执行小部件的删除方法?

2 个答案:

答案 0 :(得分:22)

确定。我搞定了。 让我解释一下这个删除,保持小部件是如何工作的。

窗口小部件的父布局已知。然后你通过布局删除它。通过做:

layout()->removeAt(widget);
delete widget;

如果在QLayout(或其子代)中使用takeAt(index),它会为您提供一个QLayoutItem。要访问里面的小部件,只需使用widget()。但是没有删除它就无法移除小部件。所以这种方法是无效的。

在Docs中,它告诉了一种删除元素的方法:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0)  {
    ...
    delete child;
}

Qt中需要注意的一点是: 如果您有布局层次结构树,则在布局内添加addLayout(),无论您的窗口小部件插入多深,都可以将其从子布局或任何父布局中删除< / strong>布局,如果布局中的树路径和此项目是从子布局构建的。

最简单的方法是在自定义表格中保留指向所有项目的指针列表。清除表格以重建它时,只需在您的小部件中执行此操作:

  CustomTableItem* item;
  while ( !items_.isEmpty() && ( (item = items_.takeFirst()) != 0 ) ){
    layout()->removeWidget(item);
    delete item; // It works no matter where the item is
  }

  items_.clear(); // clear the list afterwards.

它完美无缺,也可以自行更新布局。 如果要保留元素,只需跳过“删除项目”;并在之后使用它们。

需要注意的一点是,不同的“删除”功能在QList或类似小部件以及QLayout中的工作方式不同(我在Qt Docs上理解)。

在QList中,removeAt实际上删除了该对象。

  

(Qt 4.7 QList Docs)“删除索引位置i处的项目。我必须是列表中的有效索引位置(即0&lt; = i&lt; size())。”

在QLayout中,removeWidget或removeItem不会删除项目/小部件,你有责任删除它,就像我之前做的那样。

  

(Qt 4.7 QLayout Docs)“从布局中删除小部件小部件。在此调用之后,它是   调用者有责任为窗口小部件提供合理的几何图形   将小部件放回布局中。“

希望它有所帮助。如果你看到任何错误,你可以告诉我,我会编辑答案!

有关删除此处的更多信息: Other stackoverflow post

答案 1 :(得分:6)

Qt中的小部件是常规C ++对象,可以使用C ++ delete运算符删除任何其他对象:

delete myWidget;

在Qt中,小部件之间总是存在父子关系。当父窗口小部件被销毁时,它将删除其所有子窗口。通常,您不需要考虑显式删除任何小部件,而是考虑顶级小部件,即窗口和对话框。 Qt将负责删除任何子小部件。

QList::removeAt(int)不会删除已删除的对象,只会从列表中删除该对象。如果您还想删除对象,则必须执行以下操作:

delete myList.takeAt(0);

这适用于所有功能,例如removeAt(int)takeAt(int)takeFirst()等。它们永远不会删除对象,只会从容器中删除它们(列表,布局,滚动条等) )。在大多数情况下,窗口小部件的所有权随后被转移到调用者,(调用者负责在父子关系中断时删除窗口小部件),但不要假设总是这样,总是阅读函数的文档