qtqmlreloadhot-reloadapplicationwindow

Hot reload QML when using ApplicationWindow


Has anyone been able to hot reload all QML files when using a ApplicationWindow? I found a few examples like https://qml.guide/live-reloading-hot-reloading-qml/ and https://www.slideshare.net/ICSinc/how-best-to-realize-a-runtime-reload-of-qml, but mostly they use Loader and as ApplicationWindow needs to be the root item, this does not work (no window appears) to just reload all QML stuff.

I tried:

ApplicationWindow {
    id: window
    visibility: "FullScreen"

    Shortcut {
        sequence: "F5"
        context: Qt.ApplicationShortcut
        onActivated: {
            window.close();
            app.loadQml();
        }
    }
    ...
}

where app is a context property I set on C++ side and the function does:

void App::loadQml()
{
    qml_engine_.clearComponentCache();
    // Use "qrc:/Main.qml" for Qt Resource System.
    // Use "Main.qml" for file system.
    qml_engine_.load(QUrl(QStringLiteral("Main.qml")));
}

This code kind of works once, the window dis- and reapears but the shortcut only works once but no second time...

Any ideas how to implement this?


Solution

  • Here's what I did and it's working fine: main.cpp:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "app.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        App appp;
        appp.setEngine(&engine);
    
        engine.rootContext()->setContextProperty("app", &appp);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    app.cpp:

    #include "app.h"
    
    App::App(QObject *parent): QObject (parent)
    {
    
    }
    
    App::~App(){}
    
    void App::loadQml()
    {
        m_engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
    }
    

    app.h:

    #ifndef APP_H
    #define APP_H
    #include <QObject>
    #include <QQmlApplicationEngine>
    
    class App: public QObject
    {
    
        Q_OBJECT
    public:
        App(QObject* parent = Q_NULLPTR);
        ~App();
    
        Q_INVOKABLE void loadQml();
        void setEngine(QQmlApplicationEngine *engine) { m_engine = engine; }
    
    private:
        QQmlApplicationEngine* m_engine;
    };
    
    #endif // APP_H
    

    main.qml:

    import QtQuick 2.11
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.11
    import QtQuick.Window 2.11
    
    Window {
        id: window
        width: 1000
        height: 1000
        visible: true
    
        Shortcut {
            sequence: "F5"
            onActivated: {
                window.close()
                app.loadQml()
            }
        }
    }