Loading additional QML files
Hello,
I'm struggling with dynamic loading of *.qml files. Although my real application is way bigger I have managed to reduce the problem to following code:
(1) Single c++ application loading main.qml and then loading WindControlItem.qml
Code:
/*
* main.cpp
*/
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.
load(QUrl(QStringLiteral
("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
// Root object for finding QML Items by their objectName
QObject* root
= engine.
rootObjects()[0];
assert(root != nullptr);
// The QML Item to which we want to inject our QML-Item-loaded-from-file
QQuickItem* centralPane = qobject_cast<QQuickItem*>(root->findChild<QObject*>("centralPane"));
assert(centralPane != nullptr);
// Load the QML file to a component
QString qml_path
= "WeatherCtrlItem.qml";
QQmlComponent comp
(&engine,
QUrl::fromLocalFile(qml_path
));
// Create an instance of the component
assert(obj != nullptr);
// Up-cast it to a QQuickItem
QQuickItem *item = qobject_cast<QQuickItem*>(obj);
assert(item != nullptr);
// Born C++, die QML
engine.setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
// Set QObject-parent to the central pane
item->setParent(centralPane);
// Set Visual-parent to the central pane
item->setParentItem(centralPane);
return app.exec();
}
(2) Content of main.qml
Code:
/*
* main.qml
*/
import QtQuick 2.10
import QtQuick.Controls 1.4
ApplicationWindow {
id: root
visible: true
width: 800
height: 600
menuBar: MenuBar {
Menu {
title: "File"
MenuItem {
text: "Exit"
onTriggered: Qt.exit(0)
}
} // Menu
} // MenuBar
Rectangle {
anchors.left: parent.left
width: (parent.width * 0.2)
height: parent.height
}
// I want this item to eventually become a parent of another dynamically loaded
// item -- that's why I give it an objectName.
Rectangle {
objectName: "centralPane"
width: parent.width * 0.6
height: parent.height
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle {
width: (parent.width * 0.2)
height: parent.height
anchors.right: parent.right
}
} // ApplicationWindow
(3) Content of WindControlItem.qml
Code:
/*
* WindControlItem.qml
*/
import QtQuick 2.10
import QtQuick.Controls 1.4
Rectangle {
id: recRoot
color: "#778899"
anchors.fill: parent
GroupBox {
id: gpbLayers
title: "Wind layers"
anchors.fill: parent
Grid {
id: grdFields
anchors.fill: parent
columns: 2
Text {
text: "speed"
}
TextField {
id: fieldSpeed
placeholderText: "meters/sec"
}
Text {
text: "direction"
}
TextField {
id: fieldDir
placeholderText: "degrees"
}
Button{
text: "Add layer"
}
} // Grid
} // GroupBox
} // Item root
When I start the application the GUI displays correctly. The problem is that after I close the ApplicationWindow lots of warnings are printed to the output:
Code:
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/GroupBox.qml:184: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/GroupBox.qml:204: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/GroupBox.qml:205: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/GroupBox.qml:206: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/GroupBox.qml:216: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/Control.qml:90: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/AbstractCheckable.qml:123: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/Control.qml:90: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/TextField.qml:656: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/TextInputWithHandles.qml:104: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/TextInputWithHandles.qml:131: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/Control.qml:90: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/TextField.qml:656: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/TextInputWithHandles.qml:104: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/TextInputWithHandles.qml:131: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/Control.qml:90: ReferenceError: parent is not defined
file:///C:/tools/Qt/5.12.0/msvc2017/qml/QtQuick/Controls/Private/BasicButton.qml:194: ReferenceError: parent is not defined
I have tried to debug the code with both Qt 5.11.3 and Qt 5.12.0 but the resulting behavior is identical.
Finally my questions:
(1) Am I using correct approach for dynamic loading of Items defined in *.QML file?
(2) What could be the cause for the reference errors?
Than you for your answers!
Re: Loading additional QML files
Quote:
Originally Posted by
jforejtn
(1) Am I using correct approach for dynamic loading of Items defined in *.QML file?
Your case looks much more like the use case of a Loader.
A general rule of thumb is that you do not attempt to access QML created objects by objectName and findChild/findChildren.
This kind of dependency inversion (C++ code depending on specific objects in QML) is almost always a bad idea.
Quote:
Originally Posted by
jforejtn
(2) What could be the cause for the reference errors?
Maybe order of deletion gone wrong.
Try to not set JavaScriptOwnership, the QObject parent should be enough.
But again, this looks like a classic Loader scenario to me.
Cheers,
_