1.QWidget *parentWidget() const;
inline QWidget *QWidget::parentWidget() const
{ return static_cast<QWidget *>(QObject::parent()); }
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的选项卡的末尾,内部顺序与以前相同。
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;
}
QWidget *QWidget::find(WId id)
{
return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
}