Qt源码分析--QWidget(9)--System functions

59 篇文章 1 订阅
37 篇文章 1 订阅

1.QWidget *parentWidget() const;

inline QWidget *QWidget::parentWidget() const
{ return static_cast<QWidget *>(QObject::parent()); }

2.QWidget *window() const;


QWidget *QWidget::window() const
{
    QWidget *w = const_cast<QWidget *>(this);
    QWidget *p = w->parentWidget();
    while (!w->isWindow() && p) {
        w = p;
        p = p->parentWidget();
    }
    return w;
}

如果QWidget本身是window,则返回自身;否则,往上寻找祖先控件,直到找到带边框的控件为止。

3.void setParent(QWidget *parent);

void QWidget::setParent(QWidget *parent)
{
    if (parent == parentWidget())
        return;
    setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
}

void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
{
    Q_D(QWidget);
    Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
#ifdef QT_DEBUG
    const auto checkForParentChildLoops = qScopeGuard([&](){
        int depth = 0;
        auto p = parentWidget();
        while (p) {
            if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
                qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
                         "this is undefined behavior",
                         this, metaObject()->className(), qPrintable(objectName()));
            }
            p = p->parentWidget();
        }
    });
#endif
    bool resized = testAttribute(Qt::WA_Resized);
    bool wasCreated = testAttribute(Qt::WA_WState_Created);
    QWidget *oldtlw = window();
    if (f & Qt::Window) // Frame geometry likely changes, refresh.
        d->data.fstrut_dirty = true;
    QWidget *desktopWidget = 0;
    if (parent && parent->windowType() == Qt::Desktop)
        desktopWidget = parent;
    bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
    if (newParent && parent && !desktopWidget) {
        if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
            parent->d_func()->enforceNativeChildren();
        else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
            setAttribute(Qt::WA_NativeWindow);
    }
    if (wasCreated) {
        if (!testAttribute(Qt::WA_WState_Hidden)) {
            hide();
            setAttribute(Qt::WA_WState_ExplicitShowHide, false);
        }
        if (newParent) {
            QEvent e(QEvent::ParentAboutToChange);
            QCoreApplication::sendEvent(this, &e);
        }
    }
    if (newParent && isAncestorOf(focusWidget()))
        focusWidget()->clearFocus();
    QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData();
    QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStoreTracker : 0;
    d->setParent_sys(parent, f);
    QTLWExtra *topExtra = window()->d_func()->maybeTopData();
    QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStoreTracker : 0;
    if (oldBsTracker && oldBsTracker != bsTracker)
        oldBsTracker->unregisterWidgetSubtree(this);
    if (desktopWidget)
        parent = 0;
#ifndef QT_NO_OPENGL
    if (d->textureChildSeen && parent) {
        // set the textureChildSeen flag up the whole parent chain
        QWidgetPrivate::get(parent)->setTextureChildSeen();
    }
#endif
    if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
        if (newParent)
            oldBs->removeDirtyWidget(this);
        // Move the widget and all its static children from
        // the old backing store to the new one.
        oldBs->moveStaticWidgets(this);
    }
    // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
    if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation) && !testAttribute(Qt::WA_WState_Created))
        create();
    d->reparentFocusWidgets(oldtlw);
    setAttribute(Qt::WA_Resized, resized);
    const bool useStyleSheetPropagationInWidgetStyles =
        QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
    if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
        && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
        d->resolveFont();
        d->resolvePalette();
    }
    d->resolveLayoutDirection();
    d->resolveLocale();
    // Note: GL widgets under WGL or EGL will always need a ParentChange
    // event to handle recreation/rebinding of the GL context, hence the
    // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
    // platforms).
    if (newParent
#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || defined(QT_OPENGL_ES)
        || (f & Qt::MSWindowsOwnDC)
#endif
        ) {
        // propagate enabled updates enabled state to non-windows
        if (!isWindow()) {
            if (!testAttribute(Qt::WA_ForceDisabled))
                d->setEnabled_helper(parent ? parent->isEnabled() : true);
            if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
                d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
        }
        d->inheritStyle();
        // send and post remaining QObject events
        if (parent && d->sendChildEvents) {
            QChildEvent e(QEvent::ChildAdded, this);
            QCoreApplication::sendEvent(parent, &e);
        }
//### already hidden above ---> must probably do something smart on the mac
// #if 0 // Used to be included in Qt4 for Q_WS_MAC
//             extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
//             if(!qt_mac_is_macdrawer(q)) //special case
//                 q->setAttribute(Qt::WA_WState_Hidden);
// #else
//             q->setAttribute(Qt::WA_WState_Hidden);
//#endif
        if (parent && d->sendChildEvents && d->polished) {
            QChildEvent e(QEvent::ChildPolished, this);
            QCoreApplication::sendEvent(parent, &e);
        }
        QEvent e(QEvent::ParentChange);
        QCoreApplication::sendEvent(this, &e);
    }
#ifndef QT_NO_OPENGL
    //renderToTexture widgets also need to know when their top-level window changes
    if (d->textureChildSeen && oldtlw != window()) {
        sendWindowChangeToTextureChildrenRecursively(this);
    }
#endif
    if (!wasCreated) {
        if (isWindow() || parentWidget()->isVisible())
            setAttribute(Qt::WA_WState_Hidden, true);
        else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
            setAttribute(Qt::WA_WState_Hidden, false);
    }
    d->updateIsOpaque();
#if QT_CONFIG(graphicsview)
    // Embed the widget into a proxy if the parent is embedded.
    // ### Doesn't handle reparenting out of an embedded widget.
    if (oldtlw->graphicsProxyWidget()) {
        if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
            ancestorProxy->d_func()->unembedSubWindow(this);
    }
    if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
        if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
            ancestorProxy->d_func()->embedSubWindow(this);
    }
#endif
    if (d->extra && d->extra->hasWindowContainer)
        QWindowContainer::parentWasChanged(this);
}

如果新的父窗口widget位于不同的窗口中,则QWidget及其子窗口将附加到新父窗口widget的选项卡的末尾,内部顺序与以前相同。

4.WId winId() const;

WId QWidget::winId() const
{
    if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
#ifdef ALIEN_DEBUG
        qDebug() << "QWidget::winId: creating native window for" << this;
#endif
        QWidget *that = const_cast<QWidget*>(this);
        that->setAttribute(Qt::WA_NativeWindow);
        that->d_func()->createWinId();
        return that->data->winid;
    }
    return data->winid;
}

5.static QWidget *find(WId);

QWidget *QWidget::find(WId id)
{
    return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值