14

I have main.qml and dynamic.qml files that i want to load dynamic.qml on main.qml using Loader {}.
Content of dynamic.qml file is dynamic and another program may change its content and overwrite it. So i wrote some C++ code for detecting changes on file and fires Signal.
My problem is that I don't know how can i force Loader to reload file.

This is my current work:

MainController {
    id: mainController
    onInstallationHelpChanged: {
        helpLoader.source = "";
        helpLoader.source = "../dynamic.qml";
    }
}

Loader {
    id: helpLoader

    anchors.fill: parent
    anchors.margins: 60
    source: "../dynamic.qml"
}



I think that QML Engine caches dynamic.qml file. So whenever I want to reload Loader, it shows old content. Any suggestion?

4

2 回答 2

12

将 Loaders属性设置为空字符串,您需要调用trimComponentCache()QQmlEngine 。换句话说:source

helpLoader.source = "";
// call trimComponentCache() here!!!
helpLoader.source = "../dynamic.qml";

为此,您需要向 QML 公开一些 C++ 对象,该对象具有对您的 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";
于 2013-10-26T08:58:59.150 回答
4

我希望有一个纯粹的 QML 解决方案。我注意到这loader.source是一个 url ( file:///) 并记住了如何使用 HTML,您可以避免?t=Date.now()在请求中使用 HTTP 缓存。尝试添加?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()
        }
    }

}
于 2016-08-10T21:22:44.490 回答