20

(我使用 Qt 4.7、Windows 7、64 位)。

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

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

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

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

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

我尝试了几种方法,但无论它们发生了什么,我仍然可以看到这些小部件。

关于这个的问题:

  • 小部件何时被删除?如果我从布局中获取小部件(索引),它会在一段时间内自行删除吗?如果我在另一个列表中有指向它的指针,会发生这种情况吗?

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

4

2 回答 2

30

行。我让它工作了。让我解释一下这个删除,保留小部件是如何工作的。

小部件由其父布局知道。然后您通过布局将其删除。通过做:

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

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

在文档中,它讲述了一种删除元素的方法:

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

在 Qt 中需要特别注意的是:如果你有一个layouts 的层次结构树,在 layouts中添加了 addLayout(),无论你的 widget 插入多深,你都可以将它从子布局或任何父布局中移除布局,如果布局中的树路径和此项目是从子布局构建的。

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

  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 处的项目。i 必须是列表中的有效索引位置(即 0 <= i < size())。”

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

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

希望能帮助到你。如果您发现任何错误,您可以告诉我,我将编辑答案!

更多关于删除的信息: 其他 stackoverflow 帖子

于 2013-07-18T09:20:11.420 回答
7

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

delete myWidget;

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

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

delete myList.takeAt(0);

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

于 2013-07-17T18:30:47.063 回答