【问题标题】:About deleting, removing widgets and layouts in Qt 4关于在 Qt 4 中删除、移除小部件和布局
【发布时间】:2013-07-17 15:08:05
【问题描述】:

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

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

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

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

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

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

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

关于这个的问题:

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

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

【问题讨论】:

    标签: qt layout widget qt4


    【解决方案1】:

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

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

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

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

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

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

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

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

      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 文档中所理解的那样)。

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

    (Qt 4.7 QList Docs)"删除索引位置 i 处的项目。i 必须是列表中的有效索引位置(即 0

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

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

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

    更多关于删除的信息: Other stackoverflow post

    【讨论】:

    • layout()->removeAt(widget);只存在于 QGraphicsLayout。你的意思可能是 layout()->removeWidget(widget);
    • 这也是您可以从布局中删除小部件而不删除它的方法。如果您没有小部件指针,请执行以下操作: QLayoutItem * item = layout->itemAt(0); QWidget * widget = item->widget(); if (widget != NULL) { layout->removeWidget(widget); //如果要删除小部件,请执行:widget->setParent(NULL);删除小部件; }(格式化不起作用,但你明白了......)
    • 仅供参考:这在 Python 中无效,因为您也必须处理内部 c++ 对象。
    • 当需要从事件处理器(slot)销毁item时,需要调用item->deleteLater(),如“其他帖子”所示,否则会导致堆损坏发生。
    【解决方案2】:

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

    delete myWidget;
    

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

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

    delete myList.takeAt(0);
    

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

    【讨论】:

    • 谢谢!但是我的特殊问题呢:我有一个 QBoxLayout。我这样做: takeAt(int) 获取一个元素。它不是一个小部件,而是一个 QLayoutItem。获取我使用的小部件。小部件(无效)功能。但是小部件仍然在里面。如何取出小部件并删除该 LayoutItem?没有任何功能!
    • 仅供参考,这在 Python 中无效。你也必须照顾内部的 c++ 对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2014-09-05
    相关资源
    最近更新 更多