QT(11):关闭事件

bool QWidget::close()
{
    return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
}

调用close()方法后首先它会向widget发送一个关闭事件(QCloseEvent)。如果widget接受了关闭事件(QCloseEvent),窗口将会隐藏(实际上调用hide())。如果widget不接受关闭事件,那么窗口将什么也不做。默认情况下widget会接受关闭事件,我们可以重写QCloseEvent事件,可以选择接受或者不接受。

Qt::WA_DeleteOnClose:
如果widget设置了Qt::WA_DeleteOnClose属性,widget将会被释放。不管widget是否可见,关闭事件都会传递给widget。即接收到QCloseEvent事件后,除了调用hide()方法将窗口隐藏,同时会调用deleteLater()方法将窗口释放掉,不会再占用资源。

所以说调用close()并不一定就会将窗口对象销毁。而只有设置了 Qt::WA_DeleteOnClose属性才会删除销毁。如果这个属性没有设置,close()的作用和hide(),setvisible(false)一样,只会隐藏窗口对象而已,并不会销毁该对象。

WA_QuitOnClose:
当最后一个设置了WA_QuitOnClose属性的窗体部件关闭时(即接受了closeEvent()事件)退出应用程序。

bool QWidgetPrivate::close_helper(CloseMode mode)
{
//检查当前窗口是否关闭,关闭则返回,未关则置位--------------------------------------
    if (data.is_closing)
        return true;

    Q_Q(QWidget);
    data.is_closing = 1;
//获取父窗口--------------------------------------------------------------------
    QPointer<QWidget> that = q;
    QPointer<QWidget> parentWidget = (q->parentWidget() && !QObjectPrivate::get(q->parentWidget())->wasDeleted) ? q->parentWidget() : nullptr;
//测试是否可以在退出时同时关闭----------------------------------------------------
    bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
//判断关闭模式参数,执行不同事件处理-----------------------------------------------
    if (mode != CloseNoEvent) {
        QCloseEvent e;
        if (mode == CloseWithSpontaneousEvent)
            QApplication::sendSpontaneousEvent(q, &e);
        else
            QCoreApplication::sendEvent(q, &e);
        if (!that.isNull() && !e.isAccepted()) {
            data.is_closing = 0;
            return false;
        }
    }
//检查窗口不为空且没有隐藏,则隐藏当前窗口对象------------------------------------------
    if (!that.isNull() && !q->isHidden())
        q->hide();

    // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
//如果设置了quitonclose,检查是不是最后一个设置了该属性的窗口,如果是退出程序------------------------
    quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());

    if (quitOnClose) {
        /* if there is no non-withdrawn primary window left (except
           the ones without QuitOnClose), we emit the lastWindowClosed
           signal */
        QWidgetList list = QApplication::topLevelWidgets();
        bool lastWindowClosed = true;
//获取topLevelWidgets---------------------------------------------------
        for (int i = 0; i < list.size(); ++i) {
            QWidget *w = list.at(i);
            if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
                continue;
//如果还存在一个窗口还没有关闭:同时满足设置quitonclose属性,是可见的,没有父窗口,就不会关闭应用程序
            lastWindowClosed = false;
            break;
        }
//如果最后一个设置了quitonclose窗口关闭,就要退出程序。获取程序对象application,并进行关闭------------------------------------------------
        if (lastWindowClosed) {
            QGuiApplicationPrivate::emitLastWindowClosed();
            QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
            applicationPrivate->maybeQuit();
        }
    }

//若widget不为空,关闭置0,测试关闭删除属性,置位,调用延迟删除-------------------------------
//
    if (!that.isNull()) {
        data.is_closing = 0;
//设置了deleteonclose才会删除,释放资源,不然只是隐藏----------------------------
        if (q->testAttribute(Qt::WA_DeleteOnClose)) {
            q->setAttribute(Qt::WA_DeleteOnClose, false);
            q->deleteLater();
        }
    }
    return true;
}

setAttribute内:当前窗口设置为非模态,如果已经为非模态,将获取父窗口,如果有父窗口,设置为局部模态,否则全局模态。

enum WindowModality {
	NonModal,
	WindowModal,
	ApplicationModal
};

非模态nonModal,不会阻止其他窗口操作;
windowmodel局部模态,影响继承关系的窗体;
applicationModel应用程序模态,影响该应用的所有窗体。

模态,只能首先对模态窗口进行操作后才能操作其他窗口,本质是父线程在子线程创建模态窗口后,父线程阻塞,等待子线程完成操作
非模态,同时和其他窗口进行操作,本质是父子线程并发运行

参考:https://blog.csdn.net/goforwardtostep/article/details/53647146

你可能感兴趣的:(QT,qt,数据库,开发语言)