Reloading QQuickWindow content without window recreation
-
For qml file with
Itemelement as root of qml scene:Item { ... }it is possible to preview
qmlfile content withQQuickViewwithout window recreation - see relevant slightly modified and simplifiedqmlscenecode:QQmlEngine engine; QPointer<QQmlComponent> component = new QQmlComponent(&engine); QQuickWindow *window = nullptr; auto qxView = new QQuickView(&engine, nullptr); ... // Call this slot on file update (for example by QFileSystemWatcher signal) updatePreview() { // Recreate Qml Component engine.clearComponentCache(); component = new QQmlComponent(&engine); component->loadUrl(url); QObject *topLevel = component->create(); // Recreate Quick Window window = qobject_cast<QQuickWindow *>(topLevel); if (window) { engine.setIncubationController(window->incubationController()); } else { QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel); if (contentItem) { window = qobject_cast<QQuickWindow *>(qxView); delete qxView->rootObject(); // Clear old root object before setting new one qxView->setContent(url, component, contentItem); } } }For such
qmlfile structurewindowbecomenullptron Quick Window recreation and execution goes toelsepath ofifstatement. And there we use singleQQuickViewinstance -qxView, just modifying its content without full reloading and recreation.BTW,
QQuickView::setContent()is undocumented but used inqmlscene.However if
qmlfile containsApplicationWindowas root item of the scene:ApplicationWindow { ... }execution goes by the 1st variant of Quick Window recreation:
engine.setIncubationController(window->incubationController());and new
QQuickWindowinstance created which takes much more time and force us to destroy and close previous one.Is it possible analogous to
QQuickViewreload scene content forQQuickWindowwithout full window recreation? Thanks! -
One way to look at this is - without window creation
-
QQuickWIndow gives the invisible root item of the scene using contentItem function.
-
I can just create the item based QML object and attach this to content item(invisible root item).
-
This way we will not re-create the window, but just create the scene items and attach item to invisibleItem.
-
-
One way to look at this is - without window creation
-
QQuickWIndow gives the invisible root item of the scene using contentItem function.
-
I can just create the item based QML object and attach this to content item(invisible root item).
-
This way we will not re-create the window, but just create the scene items and attach item to invisibleItem.
@dheerendra I'd tried to use
contentItem()with no luck. Could You provide minimum working sample or few lines of code to clarify the idea please? How to create QML object from file containingApplicationWindowelement? -
-
Just check this..
======main.cpp====
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; qDebug() << engine.rootObjects().at(0)->objectName() <<endl; QObject *obj = engine.rootObjects().at(0); qDebug() << " Class Name =" << obj->metaObject()->className() <<endl; QQuickWindow *w = qobject_cast<QQuickWindow*>(obj); qDebug() << w->objectName() <<endl; QQuickItem *rootItem = w->contentItem(); QQmlComponent *comp = new QQmlComponent(&engine,QUrl(QStringLiteral("qrc:/ChildItem.qml"))); if(comp->isError()){ qWarning() << Q_FUNC_INFO << " Unable to create the component " << comp->errorString() << endl; return 1; } QObject *o1 = comp->create(); QQuickItem *childItem = qobject_cast<QQuickItem*>(o1); childItem->setParentItem(rootItem); return app.exec(); }===main.qml=======
Window { visible: true width: 440 height: 480 title: qsTr("Hello World") objectName: "TopW" }===========ChildItem.qml=========
Rectangle { width: 400;height: 400;color: "red" Component.onCompleted: { console.log("Child Item created") } } -
Just check this..
======main.cpp====
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; qDebug() << engine.rootObjects().at(0)->objectName() <<endl; QObject *obj = engine.rootObjects().at(0); qDebug() << " Class Name =" << obj->metaObject()->className() <<endl; QQuickWindow *w = qobject_cast<QQuickWindow*>(obj); qDebug() << w->objectName() <<endl; QQuickItem *rootItem = w->contentItem(); QQmlComponent *comp = new QQmlComponent(&engine,QUrl(QStringLiteral("qrc:/ChildItem.qml"))); if(comp->isError()){ qWarning() << Q_FUNC_INFO << " Unable to create the component " << comp->errorString() << endl; return 1; } QObject *o1 = comp->create(); QQuickItem *childItem = qobject_cast<QQuickItem*>(o1); childItem->setParentItem(rootItem); return app.exec(); }===main.qml=======
Window { visible: true width: 440 height: 480 title: qsTr("Hello World") objectName: "TopW" }===========ChildItem.qml=========
Rectangle { width: 400;height: 400;color: "red" Component.onCompleted: { console.log("Child Item created") } }@dheerendra this not I'd like to achieve: You propose me to change
ApplicationWindowcontent under root item. But I need to trackqmlchanges in a file which contains whether qmlItem(which works fine without reloading) orApplicationWindow. For example I have such file from tutorial:import QtQuick 2.11 import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.4 import QtQuick.Layouts 1.11 import QtQuick.Window 2.11 import Qt.labs.calendar 1.0 ApplicationWindow { id: window width: 400 height: 600 visible: true color: "red" ListView { id: alarmListView anchors.fill: parent } RoundButton { id: addAlarmButton text: "+" anchors.bottom: alarmListView.bottom anchors.bottomMargin: 8 anchors.horizontalCenter: parent.horizontalCenter onClicked: alarmDialog.open() } }and here I can change
color, add, delete or modify items, dimension (width,height), etc. And see all this changes in real time without Window recreation like forQQuickView. For now it recreates and reloadsQQuickWindowon every file change and need to close and delete old one. -
@dheerendra this not I'd like to achieve: You propose me to change
ApplicationWindowcontent under root item. But I need to trackqmlchanges in a file which contains whether qmlItem(which works fine without reloading) orApplicationWindow. For example I have such file from tutorial:import QtQuick 2.11 import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.4 import QtQuick.Layouts 1.11 import QtQuick.Window 2.11 import Qt.labs.calendar 1.0 ApplicationWindow { id: window width: 400 height: 600 visible: true color: "red" ListView { id: alarmListView anchors.fill: parent } RoundButton { id: addAlarmButton text: "+" anchors.bottom: alarmListView.bottom anchors.bottomMargin: 8 anchors.horizontalCenter: parent.horizontalCenter onClicked: alarmDialog.open() } }and here I can change
color, add, delete or modify items, dimension (width,height), etc. And see all this changes in real time without Window recreation like forQQuickView. For now it recreates and reloadsQQuickWindowon every file change and need to close and delete old one.@Aleksey_K-0
This is where I'm proposing to split the AppWIndows and Content separately. You change the content qml. It will update your AppWindow as well. In the QML what you have posted let me know what you would like to achieve with example. There are ways to monitor the changes. -
@Aleksey_K-0
This is where I'm proposing to split the AppWIndows and Content separately. You change the content qml. It will update your AppWindow as well. In the QML what you have posted let me know what you would like to achieve with example. There are ways to monitor the changes.@dheerendra https://github.com/penk/qml-livereload - this is what I try to achieve: live QML reload on file change.
QQuickViewworks here without window recreation - just changed content,ApplicationWindowandQQuickWindowforces to recreate Window on every file change which I try to avoid.This is where I'm proposing to split the AppWIndows and Content separately.
Not clear how?
You change the content qml. It will update your AppWindow as well. In the QML what you have posted let me know what you would like to achieve with example.
I mention above: edit file and see results in real time on preview application like
qmlscene.There are ways to monitor the changes.
What are they?