Repeater and itemAt issue
-
Hello, I am experimenting with QML and trying to access an item created by repeator, but am getting the error:
TypeError: Result of expression 'repeater.itemAt(0)' [null] is not an object.
I can access the repeater.count but not any items.
How can I do this?
@import QtQuick 1.1
Item {
width: parent.width
height: parent.heightRow { id: rows Repeater { id: repeater model: 10 Rectangle { width: 10; height: 20; } } } Rectangle { x: repeater.itemAt(0).x // this fails with TypeError: Result of expression 'repeater.itemAt(0)' [null] is not an object. y: 100 * repeater.count // this works width: 10; height: 10 }
}
@ -
Hi,
There are a couple issues at play here:
- The order in which the bindings are initially evaluated. In this case, repeater.itemAt(0).x is evaluated before the Repeater has actually created its children.
- The fact that methods can't NOTIFY (like properties do) when their return value would change. In this case, even when the items are finally created, repeater.itemAt(0).x is not reevaluated.
You could work around this by assigning the value (or binding) at component completion instead, e.g.
@
Component.onCompleted: myRect.x = repeater.itemAt(0).x //once-off assignment
@or
@
Component.onCompleted: myRect.x = (function(){ return repeater.itemAt(0).x; }) //binding
@Regards,
Michael -
@mbrasser :
Thanks, your advice makes sense and I tried it but I'm still getting anull
fromitemAt
.My code:
import QtQuick 2.7 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 Column { Row { Repeater { id: rectRepeater model: 3 Rectangle { width: 30 height: 30 color: "red" radius: 10 } } } Row { Repeater { model: 3 Text { Component.onCompleted: { text: rectRepeater.itemAt(0).width; } } } } } }
I'd appreciate any ideas on that one.
-
@Stefan-Monov76 Probably because the Item is not instantiated by the time this Repeater starts creating the items. You can easily solve this by delaying the creation of items in the other Repeater.
Column { anchors.fill: parent Row { Repeater { id: rectRepeater model: 3 Rectangle { width: 30 height: 30 color: "red" radius: 10 } Component.onCompleted: { textRepeater.model = 3 } } } Row { Repeater { id: textRepeater Text { text : rectRepeater.itemAt(0).width } } } }
-
@Stefan-Monov76 That is because there is no guarantee that those component have been instantiated even by then.
-
@Stefan-Monov76 My code atleast guarantees that the 2nd Repeater doesnot start instantiating items before 1st repeater have finished instantiating them because 2nd Repeater's Items depends on 1st Repeater's Item.
-
@p3c0 :
If I'm not mistaken,Component.onCompleted
fires only when the entire top-level component (in this case theWindow
) has finished loading. Even when I've put theComponent.onCompleted
handler inside my Text item. So my code only accesses the first Repeater's items when the Window has loaded. And if the Window has loaded, then the first Repeater has already instantiated its items. No? -
@Stefan-Monov76 No. Each component has this attached property.
-
@p3c0 :
Thanks again for the continued replies. I don't intend to argue or prove myself right, just to clear up the situation for myself, mind you! :)
The docs say a component is one of two things:- a type defined by the top-level element of a QML file (one type per file) - in my case, I have defined exactly one such component, and it "derives" from
Window
- an object defined inline by instantiating the
Component
type, that you can later instantiate via aLoader
object. This scenario is irrelevant here.
So my
Text
objects are not components, they are merely objects, and since they are not components, they don't have aComponent.onCompleted
signal, they use theWindow
'sComponent.onCompleted
signal.It's important to me to be strict when using the term "Component", it has a very specific meaning in QML.
- a type defined by the top-level element of a QML file (one type per file) - in my case, I have defined exactly one such component, and it "derives" from
-
@Stefan-Monov76 That's fine :)
component in this case I was referring to QML types that are inheritsItem
. I generally prefer to say QML components when referring to these types. Sorry for not being clear.
So basically any QML type that inheritsItem
has theComponent.onCompleted
signal. For eg.Text
,Rectangle
,Row
...
Here is the complete list:
http://doc.qt.io/qt-5/qml-qtquick-item.html
Look for the row named by "Inherited By". -
@Stefan-Monov76 It is an attached signal. It is mentioned here.
An attached signal handler is referred to in the same way. For example, the Component.onCompleted attached signal handler is commonly used to execute some JavaScript code when a component's creation process has been completed.