Qt删除layout的控件

Posted xy913741894

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt删除layout的控件相关的知识,希望对你有一定的参考价值。

基于某些原因,我们可能希望往一个布局内动态删除和添加新的元素,添加我们都能很清楚得看到addWidget这个接口.删除的话官方也有示例:


    QLayoutItem *child;
    while(child=this->ui->centralWidget->layout()->takeAt(0)) 
        delete child;
    


不知道是我个人理解的角度有问题还是怎么,我感觉就很奇怪,我添加一个widget的时候,是传入widget的指针,删除的时候是删除一个QLayoutItem的指针,读了半天的源代码才明白,在addWidget的时候,做了这样一些操作

void QLayout::addWidget(QWidget *w)
    addChildWidget(w);
    addItem(QLayoutPrivate::createWidgetItem(this, w));
 
 

先将传入的widget指针交给layout的所属widget,这样就实现了传入的widget成为了另一个widget的子widget,接着在删除父widget时会清理(析构)这个子widget.

void QLayout::addChildWidget(QWidget *w)
    QWidget *mw = parentWidget();
    QWidget *pw = w->parentWidget();
 
 
    //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
    //been in a layout.
    if (pw && w->testAttribute(Qt::WA_LaidOut)) 
        QLayout *l = pw->layout();
        if (l && removeWidgetRecursively(l, w)) 
#ifdef QT_DEBUG
            if (layoutDebug())
                qWarning("QLayout::addChildWidget: %s \\"%s\\" is already in a layout; moved to new layout",
                         w->metaObject()->className(), w->objectName().toLocal8Bit().data());
#endif
        
    
    if (pw && mw && pw != mw) 
#ifdef QT_DEBUG
            if (layoutDebug())
                qWarning("QLayout::addChildWidget: %s \\"%s\\" in wrong parent; moved to correct parent",
                         w->metaObject()->className(), w->objectName().toLocal8Bit().data());
#endif
        pw = 0;
    
    bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
    if (!pw && mw)
        w->setParent(mw);
    w->setAttribute(Qt::WA_LaidOut);
    if (needShow)
        QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
 
 
 
 
然后addItem是一个纯虚接口,createWidgetItem是一个工厂接口
QLayoutPrivate::QWidgetItemFactoryMethod QLayoutPrivate::widgetItemFactoryMethod = 0;
QLayoutPrivate::QSpacerItemFactoryMethod QLayoutPrivate::spacerItemFactoryMethod = 0;
QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *widget)
    if (widgetItemFactoryMethod)
        if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
            return wi;
    return new QWidgetItemV2(widget);
应该是依据相应的widget,生成相应的widgetItem(派生自QLayoutItem)
后面的就没继续读了
大意就是根据widget生成一个item加入到layout的item链表中.
 
 
接着删除的代码就能了解了,就是对这个item的链表进行清理,可以看到这个过程中没有涉及到widget的析构,所以layout清理完item之后,被加入到layout的widget没有析构掉,但这个时候原先加入进的子widget,这个时候其父widget并没有被恢复到之前的父widget.

以上是关于Qt删除layout的控件的主要内容,如果未能解决你的问题,请参考以下文章

QT删除QWidget或QLayout下的控件

QT布局管理器 Layout,如何实现窗口最大化时,控件也随着变大。

Qt ------ setSizePolicy

android java代码中设置控件的宽高单位是啥?

QT5 -- Grid Layout使用方法

QT怎么设置控件在窗口大小发生变化的时候,使控件始终居于右上角