Горячая перезагрузка QML при использовании ApplicationWindow

Кому-нибудь удавалось перезагрузить все файлы QML при использовании ApplicationWindow? Я нашел несколько примеров, например https://qml.guide/live-reloading-hot-reloading-qml/ и https://www.slideshare.net/ICSinc/how-best-to-realize-a-runtime-reload-of-qml, но в основном они используют Loader, а поскольку ApplicationWindow должен быть корневым элементом , это не работает (окно не появляется), чтобы просто перезагрузить все материалы QML.

Я пытался:

ApplicationWindow {
    id: window
    visibility: "FullScreen"

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

где app - свойство контекста, которое я установил на стороне C ++, а функция выполняет:

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")));
}

Этот код работает один раз, окно исчезает и снова исчезает, но ярлык работает только один раз, но не второй раз ...

Есть идеи, как это реализовать?


person marsl    schedule 13.03.2019    source источник
comment
Можете ли вы привести полный минимальный пример? будет легче разобраться в проблеме. Я удивлен, что это работает в первый раз, вы закрываете родительский элемент Shortcut   -  person bardao    schedule 13.03.2019


Ответы (1)


Вот что я сделал, и все работает нормально: 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()
        }
    }
}
person bardao    schedule 13.03.2019
comment
вы также можете заменить Window на ApplicationWindow, работает при каждом запуске - person bardao; 14.03.2019
comment
просто удали context: Qt.ApplicationShortcut - person bardao; 14.03.2019
comment
Спасибо за ответ @bardao. Удаление context: Qt.ApplicationShortcut действительно улучшило его. Мое приложение сейчас вылетает при выходе, но, по крайней мере, горячая перезагрузка, похоже, работает. Подробно: в некоторых случаях app является подклассом QGuiApplication, поэтому нет appp и app, как в вашем коде. Спасибо за вашу помощь! - person marsl; 14.03.2019
comment
@marsl, воспроизводящий проблему в минимальном примере, может быть чрезвычайно полезным :) - person bardao; 14.03.2019