I have a container which is being filled with dynamically created components during runtime. Each of those elements (let's call them DynamicObject
s) has a tree of subelements (Node
s), also created dynamically. What is more, The Node
components can be nested inside one another (like a tree structure).
Let the container have the id
parameter set to "main_container"
and every DynamicObject
have it set to "dynamic_object"
.
Whenever I try to address the main_container
from any of the nested Node
elements it all works fine. The problem is when I try to address the dynamic_object
from any Node
other than the root one (the one being the direct descendant / child of the dynamic_object
). It results in:
ReferenceError: dynamic_object is not defined
My question is: what might be the cause behind this behaviour? Can it have something to do with the fact those objects are dynamically created? (that was my first thought since I can always address the main_container
and it is statically declared in the qml code).
Code example: (if there is anything missing please let me now in the comments)
// Container.qml
import "container_logic.js" as Logic
Rectangle {
id: main_container
Keys.onTabPressed: {
Logic.createComponent("DynamicObject.qml", {/* some parameters */});
var dynamic_object = Logic.object;
Logic.createComponent("Node.qml",{labelText: "asdefg"}, undefined, dynamic_object)
var asdefg = Logic.object;
Logic.createComponent("Node.qml",{labelText: "tree A"}, undefined, dynamic_object)
var tree_a = Logic.object;
Logic.createComponent("Node.qml",{labelText: "a"}, undefined, asdefg)
var a = Logic.object;
Logic.createComponent("Node.qml",{labelText: "s"}, undefined, asdefg)
var s = Logic.object;
asdefg.subnodes = [a, s]
Logic.createComponent("Node.qml",{labelText: "tree B", isInput: false}, undefined, dynamic_object)
var tree_b = Logic.object;
Logic.createComponent("Node.qml",{labelText: "xyz", isInput: false}, undefined, dynamic_object)
var xyz = Logic.object;
Logic.createComponent("Node.qml",{labelText: "x", isInput: false}, undefined, xyz)
var x = Logic.object;
Logic.createComponent("Node.qml",{labelText: "y", isInput: false}, undefined, xyz)
var y = Logic.object;
Logic.createComponent("Node.qml",{labelText: "z", isInput: false}, undefined, xyz)
var z = Logic.object;
xyz.subnodes = [x,y,z]
dynamic_object.treeLeft = [asdefg, tree_a]
dynamic_object.treeRight = [tree_b, xyz]
}
}
// DynamicObject.qml
Rectangle {
id: dynamic_object
property alias treeLeft : tree_left.subnodes
property alias treeRight: tree_right.subnodes
Rectangle {
id: content_area
Node {
id: tree_left
labelText: "left"
anchors.left: parent.left
}
Node {
id: tree_right
labelText: "right"
anchors.right: parent.right
}
}
}
// Node.qml
ColumnLayout {
id: node
default property alias subnodes: subnodes_area.data
property alias labelText: label.text
Rectangle {
id: header_area
Text {
id: label
}
MouseArea {
id: mouse_area
anchors.fill: parent
hoverEnabled: true
onHoveredChanged: {
console.debug(main_container) // works fine
console.debug(dynamic_object) // **generates the error for all nodes but the root one**
}
}
}
ColumnLayout {
id: subnodes_area
anchors.top: header_area.bottom
}
}
// container_logic
var component = null
var owner = main_container
var object = null
var data = null
function createComponent(type, info, callback, container) {
callback = callback || finishComponent
owner = container || main_container
if(component != null) {
console.log("Error: a component is being loaded at this time");
return;
}
component = Qt.createComponent(type)
data = info
if(component.status === Component.Ready) {
callback()
} else if(component.status === Component.Loading) {
component.statusChanged.connect(callback)
} else {
console.log("Error loading component:", component.errorString())
}
}
function finishComponent() {
if(component.status === Component.Ready) {
object = component.createObject(owner, data)
if(object === null) {
console.log("Error creating object")
}
} else if(component.status === Component.Error) {
console.log("Error loading component:", component.errorString())
}
resetData()
}
function resetData() {
component = null;
data = null;
}
According to http://qt-project.org/doc/qt-4.8/qdeclarativedynamicobjects.html :
- If Qt.createComponent() is used, the creation context is the QDeclarativeContext in which this method is called
- If a Component{} item is defined and createObject() is called on that item, the creation context is the context in which the Component is defined
The problem was that the createComponent()
function for each subsequent Node
was called from the context of the main_container
, thus preventing the descendants from being able to resolve the dynamic_object
id.
Solved it by moving the code responsible for creating the nested Node
s to the Node.qml
file (actually to a javascript file imported by that qml document, but the result is the same).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With