Reloading QQuickWindow content without window recreation
-
For qml file with
Item
element as root of qml scene:Item { ... }
it is possible to preview
qml
file content withQQuickView
without window recreation - see relevant slightly modified and simplifiedqmlscene
code: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
qml
file structurewindow
becomenullptr
on Quick Window recreation and execution goes toelse
path ofif
statement. And there we use singleQQuickView
instance -qxView
, just modifying its content without full reloading and recreation.BTW,
QQuickView::setContent()
is undocumented but used inqmlscene
.However if
qml
file containsApplicationWindow
as root item of the scene:ApplicationWindow { ... }
execution goes by the 1st variant of Quick Window recreation:
engine.setIncubationController(window->incubationController());
and new
QQuickWindow
instance created which takes much more time and force us to destroy and close previous one.Is it possible analogous to
QQuickView
reload scene content forQQuickWindow
without 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.
-
-
@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 containingApplicationWindow
element? -
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
ApplicationWindow
content under root item. But I need to trackqml
changes 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 reloadsQQuickWindow
on 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. -
@dheerendra https://github.com/penk/qml-livereload - this is what I try to achieve: live QML reload on file change.
QQuickView
works here without window recreation - just changed content,ApplicationWindow
andQQuickWindow
forces 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?