Dynamically reparenting objects in QML fails on initial load
qml, qt
Solution
Easy way of doing it is placing extra `Item` under your delegate. This will cause `Repeater` to reparent `Item` and your own code would set new parent of its child, your `Rectangle` element. Like this:
import QtQuick 1.1
Rectangle {
id: container
height: 300
width: 300
signal completed
ListModel {
id: fooModel
ListElement { data: "red" }
ListElement { data: "red" }
ListElement { data: "blue" }
}
Component.onCompleted: {
console.log("Rect Completed!")
container.completed()
}
// The object I want to dynamically move
Component {
id: delg
Item {
Rectangle {
id: moveable
height: 40; width: 100
border.width: 1; border.color: "black"
state: model.data
color: state
// The following code makes it work, but feels very hackish
/*Connections {
target: container
onCompleted: {
moveable.parent = moveable.state == "red" ? red_col : blue_col
}
}*/
onStateChanged: { console.log("New state: " + state) }
onParentChanged: { console.log("New parent: " + parent) }
Component.onCompleted: { console.log("Delegate Completed!") }
MouseArea {
anchors.fill: parent
onClicked: {
// I know this is bad to do, but in my REAL application,
// the change is triggered through the model, not the qml
// object
moveable.state = (moveable.state == "red" ? "blue" : "red")
}
}
states: [
State {
name: 'red'
ParentChange { target: moveable; parent: red_col; x: 0 }
},
State {
name: 'blue'
ParentChange { target: moveable; parent: blue_col; x: 0 }
}
]
transitions: [ Transition {
ParentAnimation {
NumberAnimation { properties: 'x,y,height,width' }
}
}]
}
}
}
// Generates the Objects
Repeater {
id: repeat
model: fooModel
delegate: delg
}
// Display
Row {
spacing: 100
Column {
id: red_col
spacing: 10
width: 100; height: 300
move: Transition { NumberAnimation { properties: "y" } }
add: Transition { NumberAnimation { properties: "y" } }
}
Column {
id: blue_col
spacing: 10
width: 100; height: 300
move: Transition { NumberAnimation { properties: "y" } }
add: Transition { NumberAnimation { properties: "y" } }
}
}
}
Problem
I am trying to dynamically reparent QML objects generated in a repeater according to data they inherit from their model. This works like a charm - with one catch. When the object is generated for the first time, it is automatically reparented to the Repeater's parent after the state's ParentChange object makes its changes. Run the following QML file in a QML viewer, paying attention to the order of the console messages to see what I'm describing. After you've clicked on each of the objects, they behave as expected. ``` import QtQuick 1.1 Rectangle { id: container height: 300 width: 300 signal completed ListModel { id: fooModel ListElement { data: "red" } ListElement { data: "red" } ListElement { data: "blue" } } Component.onCompleted: { console.log("Rect Completed!") container.completed() } // The object I want to dynamically move Component { id: delg Rectangle { id: moveable height: 40; width: 100 border.width: 1; border.color: "black" state: model.data color: state // The following code makes it work, but feels very hackish /*Connections { target: container onCompleted: { moveable.parent = moveable.state == "red" ? red_col : blue_col } }*/ onStateChanged: { console.log("New state: " + state) } onParentChanged: { console.log("New parent: " + parent) } Component.onCompleted: { console.log("Delegate Completed!") } MouseArea { anchors.fill: parent onClicked: { // I know this is bad to do, but in my REAL application, // the change is triggered through the model, not the qml // object moveable.state = (moveable.state == "red" ? "blue" : "red") } } states: [ State { name: 'red' ParentChange { target: moveable; parent: red_col; x: 0 } }, State { name: 'blue' ParentChange { target: moveable; parent: blue_col; x: 0 } } ] transitions: [ Transition { ParentAnimation { NumberAnimation { properties: 'x,y,height,width' } } }] } } // Generates the Objects Repeater { id: repeat model: fooModel delegate: delg } // Display Row { spacing: 100 Column { id: red_col spacing: 10 width: 100; height: 300 move: Transition { NumberAnimation { properties: "y" } } add: Transition { NumberAnimation { properties: "y" } } } Column { id: blue_col spacing: 10 width: 100; height: 300 move: Transition { NumberAnimation { properties: "y" } } add: Transition { NumberAnimation { properties: "y" } } } } } ``` I figured out a way to fix the behavior, but it's not pretty. (See the commented out "Connections" code above for that fix). Is there a cleaner/less-hacky way to accomplish the same thing I'm trying here?