QTabWidget改变了控件的父子关系

     最近在使用QTabWidget控件的时候发现,QTabWidget控件的addTab(pWidget, "myTab")方法会改变pWidget控件原有父子关系,因为这个问题,害我找了半天,我本意是想通过pWidget->parent()获取pWidget的父指针,但是由于addTab会改变pWidget的原来的父子关系,导致找不到原来的父指针,下面我们来看看addTab是怎么来改变这个父指针的:
   首先看一段简单的应用代码:
    #ifndef _INFO_H
    #define _INFO_H
 
 
    #include <QtGui>
    class CInfo1 : public QWidget {
        public:
           CInfo1(QWidget *parent) : QWidget(parent)
           {
           }
           void getResult();
 
 
    };
 
 
    class CInfo2 : public QWidget {
        public:
           CInfo2(QWidget *parent) : QWidget(parent)
           {
           }
           void getResult();
 
 
    };
 
 
    class CInfo : public QTabWidget {
 
 
        public:
           CInfo(QWidget *parent = NULL) : QTabWidget(parent)
           {
                pInfo1 = new CInfo1(this);
                pInfo2 = new CInfo2(this);
                addTab(pInfo1, "info1");
                addTab(pInfo2, "info2");
                a = 1;
                b = 2;
                qDebug() << a << b;
           }
           CInfo1 *pInfo1;
           CInfo2 *pInfo2;
           int a;
           int b;
    };
    #endif
    #include "info.h"
    void CInfo1::getResult()
    {
        CInfo *pInfo = (CInfo *)parent();
        qDebug() << pInfo->a << pInfo->b;
    }
    void CInfo2::getResult()
    {
         CInfo *pInfo = (CInfo *)parent();
         qDebug() << pInfo->a << pInfo->b;
    }
    int main(int argc, char *argv[])
    {
         QApplication a(argc, argv);
         CInfo info;
         info.pInfo1->getResult();
         info.pInfo2->getResult();
         info.show();
         return a.exec();
    }
   从上面的代码若父指针没有更改,则会打印出三行:
             1 2
             1 2
             1 2
   而事实的打印却是:
             1 2
             X X
             X X
   X是一个随机数,从而我们不难发现,getResult()函数里的parent()已不是指向info对象了,接下来我们看看到底addTab是怎么改变父指针的,看一下调用关系:
     addTab(pInfo1, "info1");
     int QTabWidget::addTab(QWidget *child, const QString &label)
     {
         return insertTab(-1, child, label);
     }
     int QTabWidget::insertTab(int index, QWidget *w, const QIcon& icon, const QString &label)
     {
         Q_D(QTabWidget);
         if(!w)
            return -1;
         index = d->stack->insertWidget(index, w);
         d->tabs->insertTab(index, icon, label);
         setUpLayout();
         tabInserted(index);
         return index;
     }
     int QStackedWidget::insertWidget(int index, QWidget *widget)
     {
         return d_func()->layout->insertWidget(index, widget);
     }
     int QStackedLayout::insertWidget(int index, QWidget *widget)
     {
         Q_D(QStackedLayout);
         addChildWidget(widget);
         index = qMin(index, d->list.count());
         if (index < 0)
            index = d->list.count();
         QWidgetItem *wi = QLayoutPrivate::createWidgetItem(this, widget);
         d->list.insert(index, wi);
         invalidate();
         if (d->index < 0) {
              setCurrentIndex(index);
         } else {
              if (index <= d->index)
                  ++d->index;
              if (d->stackingMode == StackOne)
                  widget->hide();
              widget->lower();
         }
         return index;
     }
     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
     }
   从调用栈(注意红色代码)发现,最终addTab会调用addChildWidget,在w->setParent会将pWidget的父指针更改,哈哈,终于水落石出了。
 

你可能感兴趣的:(QTabWidget改变了控件的父子关系)