Загрузчик QML не показывает изменений.файл qml
Я main.qml
и dynamic.qml
файлы, которые я хочу загрузить dynamic.qml
on main.qml
С помощью Loader {}
.
Содержание dynamic.qml
файл динамический, и другая программа может изменить его содержимое и перезаписать его.
Поэтому я написал код C++ для обнаружения изменений в файле и сигнала пожаров.
Моя проблема в том, что я не знаю, как заставить Loader перезагрузить файл.
это моя текущая работа:
MainController {
id: mainController
onInstallationHelpChanged: {
helpLoader.source = "";
helpLoader.source = "../dynamic.qml";
}
}
Loader {
id: helpLoader
anchors.fill: parent
anchors.margins: 60
source: "../dynamic.qml"
}
Я думаю, что QML Engine кэширует . Поэтому, когда я хочу перезагрузить Loader, он показывает старый контент. Есть предложения?
2 ответов
нужно позвонить trimComponentCache()
на QQmlEngine после вы установили погрузчики source
свойство пустой строки. Другими словами:
helpLoader.source = "";
// call trimComponentCache() here!!!
helpLoader.source = "../dynamic.qml";
для этого вам нужно будет предоставить некоторый объект c++ QML, который имеет ссылку на ваш QQmlEngine (много примеров в Qt и на StackOverflow, чтобы помочь с этим).
trimComponentCache говорит QML забыть обо всех компонентах, которые он не использует, и делает только то, что вы хотеть.
обновление - объясняя немного подробнее:
например, где-то вы определяете класс, который берет указатель на ваш QQmlEngine и предоставляет метод trimComponentCache:
class ComponentCacheManager : public QObject {
Q_OBJECT
public:
ComponentCacheManager(QQmlEngine *engine) : engine(engine) { }
Q_INVOKABLE void trim() { engine->trimComponentCache(); }
private:
QQmlEngine *engine;
};
затем, когда вы создаете свой QQuickView, свяжите одно из вышеперечисленных свойств как свойство контекста:
QQuickView *view = new QQuickView(...);
...
view->rootContext()->setContextProperty(QStringLiteral("componentCache", new ComponentCacheManager(view->engine());
тогда в вашем QML вы можете сделать что-то вроде:
helpLoader.source = "";
componentCache.trim();
helpLoader.source = "../dynamic.qml";
Я надеялся на чистое решение QML. Я заметил это loader.source
- это URL-адрес (file:///
) и вспомнил, как с HTML вы можете избежать кэширования HTTP с помощью ?t=Date.now()
в ваши запросы. Пробовал добавить ?t=1234
до конца loader.source
, и, конечно же, это работает.
import QtQuick 2.0
Item {
Loader {
id: loader
anchors.fill: parent
property string filename: "User.qml"
source: filename
function reload() {
source = filename + "?t=" + Date.now()
}
}
Timer {
id: reloadTimer
interval: 2000
repeat: true
running: true
onTriggered: {
loader.reload();
}
}
}
Я также написал еще один пример, который будет проверять наличие изменений в содержимом файла перед запуском перезагрузки с помощью XMLHttpRequest.
import QtQuick 2.0
Item {
Loader {
id: loader
anchors.fill: parent
property string filename: "AppletUser.qml"
property string fileContents: ""
source: ""
function reload() {
source = filename + "?t=" + Date.now()
}
function checkForChange() {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4) {
if (loader.fileContents != req.responseText) {
loader.fileContents = req.responseText;
loader.reload();
}
}
}
req.open("GET", loader.filename, true);
req.send();
}
onLoaded: {
console.log(source)
}
Timer {
id: reloadTimer
interval: 2000
repeat: true
running: true
onTriggered: loader.checkForChange()
}
Component.onCompleted: {
loader.checkForChange()
}
}
}