正确地重新加载 QQmlApplicationEngine

Properly reloading a QQmlApplicationEngine

我有一个基于 QML 的应用程序,它从文件系统加载一个 main.qml 文件,如下所示:

myEngine->load("main.qml");

这工作正常,但我想 "reload" 引擎以防 main.qml 被更新的版本替换。

到目前为止我尝试的是再次调用 load(),假设引擎会像在其他 Qt 中一样自动重置自身 类。

不幸的是,情况并非如此。如果我再次调用该方法,另一个 window 将出现更新后的 qml 文件的内容,而原来的 window 保持打开状态并继续显示旧的 qml 文件。

为了解决这个问题,我尝试调用 load(QUrl()),然后调用 clearComponentCache() 和对新文件的最终加载调用。这导致相同的效果。

关于如何在应用程序处于 运行 时 "properly" 重新加载 QML 引擎的任何想法?

我会尝试将 myEngine 存储为堆上的指针,并在调用 quit() 后将其删除。然后你可以重建它以获得新版本的QML文件。

如果您出于某种原因不想这样做(例如,因为您想保留 window 或其他原因),您可以尝试使用 Loader 并加载 QML 文件那样。你的 main.qml 看起来像这样:

import QtQuick 2.0

Loader {
     source: "changing.qml"
}

每当您检测到 changing.qml 已更改时,只需切换 Loaderactive 属性 即可触发文件的重新加载。

刚刚看到这个,但如果您仍在尝试解决这个问题 - 这是一个三步过程,您已经掌握了一些。

  1. 您必须先关闭由 QQmlApplicationEngine 创建的 window。在我的例子中,我将第一个根对象从 QQmlApplicationEngine 中拉出并将其转换为 QQuickWindow,然后调用 close().

  2. 现在您可以在 QQmlApplicationEngine 上调用 clearComponentCache

这就是我的 window 关闭代码所做的(请注意,我给了我的主要 window 一个 objectName

QObject* pRootObject = in_pQmlApplicationEngine->rootObjects().first();
Q_ASSERT( pRootObject != NULL );
Q_ASSERT( pRootObject->objectName() == "mainWindow" );

QQuickWindow* pMainWindow = qobject_cast<QQuickWindow*>(pRootObject);
Q_ASSERT( pMainWindow );
pMainWindow->close();

第三步当然是加载您的 QML。

后来,我开始创建 QQuickView window 而不是 QQmlApplicationEngine,这样我就可以调用 clearComponentCache 然后 setSource (我不喜欢用户看到 UI window 消失然后重新出现。)