Reputation: 7400
I want to align my list of phone numbers with one field ("name") on the left side and another field ("phone") on the right side. However when trying to bind anchor properties inside the delegate, it says that the delegate object is not a parent of the ListView component. How do I reach other components from the delegate?
This is my QML code:
import QtQuick 2.7
import QtQuick.Controls 2.0
Item {
id: enclosing_area
width: 500
height: 300
ListModel {
id: dataModel
ListElement {
name: "John Smith"
phone: "1111-1111"
}
ListElement {
name: "Peter Poter"
phone: "2222-2222"
}
ListElement {
name: "Anna Lasalle"
phone: "3333-3333"
}
}
ListView {
id: list
width: enclosing_area.width
height: enclosing_area.height
model: dataModel
delegate: Rectangle {
width: enclosing_area.width
border.color: "red"
Label {
text: name
anchors.left: list.left
}
Label {
text: phone
anchors.right: list.right
}
}
}
}
qmlscene produces the following errors:
file:///LViewTest.qml:36:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
file:///LViewTest.qml:32:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
file:///LViewTest.qml:36:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
file:///LViewTest.qml:32:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
file:///LViewTest.qml:36:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
file:///LViewTest.qml:32:13: QML Label: Cannot anchor to an item that isn't a parent or sibling.
Lines 32 and 32 are "anchors.left" and "anchors.right" statements. How do I bind to properties in another objects from the delegate in my case?
Upvotes: 2
Views: 5915
Reputation: 13711
At first:
It would be convention to call your enclosing_area
root
instead.
Secondly, if you don't anchor to a sibling, don't use the id
of the object you want to anchor to, but use parent
.
This prevents you from having your errors, as - what you are trying to do - is not anchoring to the parent of the Label
s, but to their parent
s parent
.
The parent
of the Label
would be the Rectangle
in your delegate
.
ListView {
id: list // <- This is not the parent of the Labels, but of the delegateRectangle
width: enclosing_area.width // works
height: enclosing_area.height // works
// anchors.fill: parent <- would do the same, more flexible, and only one line.
model: dataModel
delegate: Rectangle {
id: delegateRectangle // <--- This is the parent of the two Labels
width: enclosing_area.width
height: 30 // <- a heightis necessary.
// As the objects are repositioned you need to set it explicitely
// and can't use anchoring. You could use the
// implicit height of it's children, to make it nice
border.color: "red"
Label {
text: name
anchors.left: delegateRectangle.left // this would work instead.
// list.left woudl try to anchor to the 'grandparent'
}
Label {
text: phone
anchors.right: parent.right // this would be the reccomended way.
// Would also anchor to delegateRectangle
}
}
}
Why should you prefer to anchor to parent
rather than your parent
s id
?
The object will (almost) always have a visual parent, but this visual parent could change. Either because you add an extra layer in code, later - or even during runtime, by reparenting it. So you would always need to update the anchors as well.
Therefore, anchoring to parent
resolves one easy error.
Upvotes: 4
Reputation: 104589
Take advantage of anchors instead of trying to hardcode the size of a child element to match its parent. That will enable you to use anchors all the way down. (Similarly, use anchor margins instead of hardcoded x,y values). You get a lot of other benefits with anchors.
ListView {
id: list
anchors.fill: parent
model: dataModel
delegate: Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 50 // you need a height otherwise all rows are on the same line
border.color: "red"
Label {
text: name
anchors.left: parent.left
}
Label {
text: phone
anchors.right: parent.right
}
}
}
}
Upvotes: 2