Почему установка флага Qt::SplashScreen предотвращает закрытие

Я имею QMainWindow который вставляет QQuickWidget,
QQuickWidget отображать две разные qml (splash.qml а также main.qml) в зависимости от состояния приложения (инициализировано или нет).

Я хочу, чтобы мое окно находилось в режиме заставки, когда splash.qml отображается, так что я сделал:

MainWindow::MainWindow(QMainWindow * parent) :QMainWindow(parent)
{
    QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);

    mDefaultFlags = windowFlags();
    setAttribute(Qt::WA_DeleteOnClose, true);
    setWindowFlags(Qt::SplashScreen);

    mQuickWidget = new QQuickWidget(this);
    //...
    setCentralWidget(mQuickWidget);

    mQuickWidget->show();
}

QML запускает слот после завершения инициализации и загрузки другого файла qml. Затем я возвращаю флаги к их значению по умолчанию, чтобы вернуться с заставки:

void MainWindow::UpdateWindowAfterInit()
{
    setWindowFlags(mDefaultFlags);
    show();
}

Все идет как положено, но когда я пытаюсь закрыть свое приложение, оно никогда не достигает конца main() в то время как это близко, если я не применяю Qt::SplashScreen флаг.

Что я должен сделать, чтобы закрыть приложение?

1 ответ

Решение

Прежде всего, давайте попробуем понять, почему это не работает так, как вы ожидаете.

Глядя на документацию QWidget::closeУ нас есть следующее (выделение мое):

QApplication::lastWindowClosed() сигнал испускается, когда последнее видимое главное окно (т.е. окно без родителя) сQt::WA_QuitOnClose набор атрибутов закрыт. По умолчанию этот атрибут установлен для всех виджетов, кроме переходных окон, таких как заставки, окна инструментов и всплывающие меню.

С другой стороны, у нас есть это для Qt::WA_QuitOnClose:

Заставляет Qt выйти из приложения, когда последний виджет с установленным атрибутом принял closeEvent(), Это поведение можно изменить с помощью QApplication::quitOnLastWindowClosed имущество. По умолчанию этот атрибут установлен для всех виджетов типа Qt::Window,

Следовательно, есть подозрение, что установленные вами атрибуты или вы думаете, что они на самом деле сбрасываются при изменении флагов.

Глядя на код, мы имеем следующее:

  • Вот фактическая реализация setWindowFlags, Вы можете видеть, что функция adjustQuitOnCloseAttribute вызывается, если старый тип был окном (то есть, если у вас было Qt::Window флаг установлен и это ваше дело).

  • Вот фактическая реализация adjustQuitOnCloseAttribute и это происходит:

    // ...
    
    if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
        q->setAttribute(Qt::WA_QuitOnClose, false);
    
    // ...
    

    Это означает, что атрибут Qt::WA_QuitOnClose установлен в false когда вы установите флаг Qt::SplashScreen,

Наконец, у нас есть следующее для Qt::WA_DeleteOnClose:

Заставляет Qt удалить этот виджет, когда он принял событие закрытия (см. QWidget::closeEvent()).

Ибо у вас больше нет Qt::WA_QuitOnClose установить, окно больше не принимает close событие и оно не уничтожено.

Что еще более важно, он не закрыт, это то, что вы наблюдаете в своей заявке. Это не ошибка Qt, это (довольно плохо) задокументированное предполагаемое поведение.


Теперь мы можем попытаться понять, что делать, чтобы решить проблему.

Возможно, достаточно установить правильные флаги и атрибуты в правильном порядке, чтобы обойти это.
Я не уверен в этом, но вы можете попробовать:

setWindowFlags(Qt::SplashScreen);
setAttribute(Qt::WA_QuitOnClose, true);
setAttribute(Qt::WA_DeleteOnClose, true);
Другие вопросы по тегам