为什么QMdiarea与子窗口直接的信号与槽在setparent之后会不起作用?

本文深入探讨了在Qt的MDI框架中,使用自定义类继承QMdiArea和QMdiSubWindow时,通过setParent操作导致信号与槽连接断开的问题。分析了源代码中viewportEvent事件的处理逻辑,以及disconnectSubWindow函数如何切断子窗口的信号与槽联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

信号与槽会失联,一般是因为其中一个对象被delete了,再就是人为地调用了disconnect()函数.

回到正题,在使用Qt的MDI框架时,我用类A和类B分别继承了QMdiArea和QMdiSubWindow,再分别实例化出A_obj,B_obj,把B_obj

放到A_obj中,后面因为功能需要,我通过setParent的方式将B_obj从A_obj中独立出来,这会,先前A_obj与B_obj建立好的信号-槽就失效了.

 

查看了源码才知道原因:

源码片段1:

bool QMdiArea::viewportEvent(QEvent *event)
{
    Q_D(QMdiArea);
    switch (event->type()) {
    case QEvent::ChildRemoved: {
        d->isSubWindowsTiled = false;
        QObject *removedChild = static_cast<QChildEvent *>(event)->child();
        for (int i = 0; i < d->childWindows.size(); ++i) {
            QObject *child = d->childWindows.at(i);
            if (!child || child == removedChild || !child->parent()
                    || child->parent() != viewport()) {
                if (!testOption(DontMaximizeSubWindowOnActivation)) {
                    // In this case we can only rely on the child being a QObject
                    // (or 0), but let's try and see if we can get more information.
                    QWidget *mdiChild = qobject_cast<QWidget *>(removedChild);
                    if (mdiChild && mdiChild->isMaximized())
                        d->showActiveWindowMaximized = true;
                }
                d->disconnectSubWindow(child);
                const bool activeRemoved = i == d->indicesToActivatedChildren.at(0);
                d->childWindows.removeAt(i);
                d->indicesToActivatedChildren.removeAll(i);
                d->updateActiveWindow(i, activeRemoved);
                d->arrangeMinimizedSubWindows();
                break;
            }
        }
        d->updateScrollBars();
        break;
    }
    case QEvent::Destroy:
        d->isSubWindowsTiled = false;
        d->resetActiveWindow();
        d->childWindows.clear();
        qWarning("QMdiArea: Deleting the view port is undefined, use setViewport instead.");
        break;
    default:
        break;
    }
    return QAbstractScrollArea::viewportEvent(event);
}
从源码片段1中,我们可以知道,当使用setParent后,B_obj独立出来,那么A_obj的孩子就少了一个,于是会触发viewportEvent(QEvent *event)事件,继而会调用d->disconnectSubWindow(child);那么这个disconnectSubWindow函数又做了些什么呢?
void QMdiAreaPrivate::disconnectSubWindow(QObject *subWindow)
{
    if (!subWindow)
        return;

    Q_Q(QMdiArea);
    QObject::disconnect(subWindow, 0, q, 0);
    subWindow->removeEventFilter(q);
}

看到倒数第二句便知,此时切断了与孩子的所有信号与槽的联系.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值