正确地重新加载QQmlApplicationEngine

Bas*_*Ben 4 qt qml qqmlapplicationengine

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

myEngine->load("main.qml");
Run Code Online (Sandbox Code Playgroud)

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

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

不幸的是,这种情况并非如此.如果我再次调用该方法,将出现另一个窗口,其中包含更新的qml文件的内容,而原始窗口保持打开状态并继续显示旧的qml文件.

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

任何想法如何在应用程序运行时"正确"重新加载QML引擎?

Mit*_*tch 5

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

如果您出于某种原因不想这样做(例如,因为您想保留窗口或其他原因),您可以尝试使用 aLoader并以这种方式加载 QML 文件。然后你main.qml会看起来像这样:

import QtQuick 2.0

Loader {
     source: "changing.qml"
}
Run Code Online (Sandbox Code Playgroud)

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

  • 呃。我想我应该收拾行李回家了。太明显了,让人心疼。谢谢!在这里,有一些代表点。:) (3认同)
  • 我无法通过使用指针和退出以任何方式做到这一点,我会调用退出并连接到退出信号,尝试删除它总是会导致崩溃,尝试断开连接(),deleteLater()但无济于事,装载机解决方案完美运行 (2认同)

小智 5

刚看到这个,但是如果你还在试图解决这个问题 - 这是一个三步过程,你有一些.

  1. 你必须关闭QQmlApplicationEngine第一个创建的窗口.在我的情况下,我将第一个根对象拉出QQmlApplicationEngine并将其转换为QQuickWindow,然后调用close().

  2. 现在你可以打电话clearComponentCacheQQmlApplicationEngine.

这是我的窗口关闭代码所做的(注意我给了我的主窗口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();
Run Code Online (Sandbox Code Playgroud)

第三步当然是加载你的QML.

后来,我开始创建一个QQuickView窗口而不是QQmlApplicationEngine,所以我可以调用clearComponentCache然后setSource(我不喜欢用户看到UI窗口消失然后重新出现.)