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