清除 QLayout 的子成员

发布时间 2023-10-30 19:20:18作者: Jeffxue

清除布局 QLayout 中的子成员,其子成员一般为 QWidgetQLayoutQSpacerItem,如下图Layout中的成员包含: QPushButton, QHBoxLayout,QSpacerItem

其对应的创建和删除代码如下:

/// <summary>
/// 为 widget 控件添加子成员
/// </summary>
void Demo01_GUI::CreateChildItems()
{
    // 1. 创建子成员
    QPushButton* btn01 = new QPushButton("button 01");
    QPushButton* btn02 = new QPushButton("button 02");
    QHBoxLayout* subLayout01 = new QHBoxLayout();
    QHBoxLayout* subLayout02 = new QHBoxLayout();
    QSpacerItem* space = new QSpacerItem(40, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);

    // 2. 将子成员添加到Layout中
    QVBoxLayout* vLayout = new QVBoxLayout();
    vLayout->addWidget(btn01);
    vLayout->addWidget(btn02);
    vLayout->addLayout(subLayout01);
    vLayout->addLayout(subLayout02);
    vLayout->addSpacerItem(space);

    // 3. 设置当前Widget的布局为 QVBoxLayout
    ui.widget01->setLayout(vLayout);
}


/// <summary>
/// 清空 Layout 中的所有 QWidget 和 子QLayout 成员
/// </summary>
void Demo01_GUI::ClearLayoutChild()
{
    // 1. 获取当前 Widget 的布局
    QLayout* curLayout = ui.widget01->layout();

    if(curLayout == nullptr)
    {
        return;
    }

    // 2. 当前布局所包含的成员个数
    int chidItemCount = curLayout->count();
    if(chidItemCount == 0)
    {
        return;
    }

    // 3. 获取当前布局中的 QWidget, QLayout和 QSpacerItem 成员,并将其删除
    QLayoutItem* child;
    while((child = curLayout->takeAt(0)) != 0)
    {
        QWidget* widget = child->widget();
        QLayout* layout = child->layout();
        QSpacerItem* sp = child->spacerItem(); // 当其它成员都被删除后,QSpacerItem 默认会被删除,因此可以省略对该控件的操作

        if(widget != nullptr)
        {
            curLayout->removeWidget(widget);
            delete widget;
        }

        if(layout != nullptr)
        {
            curLayout->removeItem(layout);
            delete layout;
        }

        // 删除 QSpacerItem 可省略,最后会被自动删除掉
        if(sp != nullptr)
        {
            curLayout->removeItem(sp);
            delete sp;
        }
    }
}

  1. QLayoutItem: 为 QLayout 中的所有子成员,它被 QLayout, QSpacerItem, 和 QWidgetItem所继承。也就是说 QLayout的成员只有上面的这三种,可以分别通过 widget(), layout(), spacerItem() 来获取,如果不存在则返回 nullptr
  2. 以上删除子成员的核心代码是通过一个 while 循环来实现的,虽然 QLayout的子成员都是通过 QLayoutItem*表示,但是在删除的时候必须要获取到 Item 中的具体 QWidget,或 QLayout ,不能直接调用 curLayout->removeItem(child)来删除 QLayoutItem,如下的方式只是让子成员不属于 QLayout,但该成员依然存在。
while((child = curLayout->takeAt(0)) != 0)
{
   // 该方案只是将当前的 Layout 中的子成员从父控件中删除,但是对应的对象还存在,只是没有布局了。
   // 此时该控件的成员个数为0,但子控件依然会混乱的显示。
   curLayout->removeItem(child);
   delete child;
}