1

I am working on a project which has QML something like:

    Item {
        id: cameraButtonBar
        ...
        Row {
            Repeater {
                id: repeaterId
                model: cameraModel.cameraPositions()

                Item {

                    Rectangle {
                        id: fullSelectedCameraMarker
                        ...
                        visible: cameraButtonBar.checkCaptured(index, false, false)
                    }
                    Rectangle {
                        id: map1SelectedCameraMarker
                        ...
                        visible: cameraButtonBar.checkCaptured(index, true, false)
                    }
                    Rectangle {
                        id: map2SelectedCameraMarker
                        ...
                        visible: cameraButtonBar.checkCaptured(index, false, true)
                    }
                }
            }
        }
    }

In my script "checkCaptured" JavaScript:

        function checkCaptured(idx, left, right) {
//Can't do anything until an image is selected
            if ( root.selectedImageIdx >= 0 ) {
                var chkItem = repeaterId.itemAt(idx);

                if ( typeof chkItem === "object" ) {
                    var marker;

                    if ( left === false && right === false ) {
                        marker = chkItem.fullSelectedCameraMarker;
                    } else if ( left === true ) {
                        marker = chkItem.map1SelectedCameraMarker;
                    } else if ( right === true ) {
                        marker = chkItem.map2SelectedCameraMarker;
                    }
                    if ( marker !== undefined ) {

                    }
                }
            }
            return false;
        }

The above isn't correct and the question is, how to I access the rectangles using the IDs in each rectangle so I get the rectangle used in the repeater?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
SPlatten
  • 5,334
  • 11
  • 57
  • 128

1 Answers1

2

As you are using the item which contains those 3 rectangles in as a delegate, you won't have access IDs from outside of the delegate. IDs are translated to actual objects at compile time and they are not intended to reference objects at runtime.

Anyway, manipulating delegates from the outside is not a good idea. Pass the required data to your delegate and let it decide what to do itself.

You can assign the inner rectangles to a read-only property of the chkItem and reference them later in your function.

Item {
    readonly property Rectangle _fullSelectedCameraMarker: fullSelectedCameraMarker
    readonly property Rectangle _map1SelectedCameraMarker: map1SelectedCameraMarker
    readonly property Rectangle _map2SelectedCameraMarker: map2SelectedCameraMarker

    Rectangle {
        id: fullSelectedCameraMarker
        ...
        visible: cameraButtonBar.checkCaptured(index, false, false)
    }
    Rectangle {
        id: map1SelectedCameraMarker
        ...
        visible: cameraButtonBar.checkCaptured(index, true, false)
    }
    Rectangle {
        id: map2SelectedCameraMarker
        ...
        visible: cameraButtonBar.checkCaptured(index, false, true)
    }
}

You can also name your object using objectName property and find them by iterating over children property of the chkItem and checking the rectangle by its objectName

Rectangle {

    id: fullSelectedCameraMarker
    objectName: "fullSelectedCameraMarker"
    ...
    visible: cameraButtonBar.checkCaptured(index, false, false)
}
var chkItem = repeaterId.itemAt(idx);
var chkItemChildren = chkItem.children;
// iterate over children using any machanism you prefer to filter those children
// 
for( var i = 0 ; i < chkItemChildren.length ; ++i)
{
    if(chkItemChildren[i].objectName==='fullSelectedCameraMarker'){
        // whatever you want to do
    }
}

Note: You can use Lodash in QML which will help a lot.

Soheil Armin
  • 2,725
  • 1
  • 6
  • 18
  • Thank you, I've since discovered a better solution which doesn't involve searching or traversing a list. – SPlatten Nov 07 '19 at 09:32
  • @SPlatten, I just update the answer. manipulating delegates from the outside is not a good idea. – Soheil Armin Nov 07 '19 at 09:49
  • Why do you use `var` in `readonly property var _fullSelectedCameraMarker: fullSelectedCameraMarker`? Using `var` when you know it is an `QtObject` or even an `Item` is no good idea either. – derM - not here for BOT dreams Nov 07 '19 at 16:45
  • @derM, please explain or reference somewhere explaining why it is bad. thank you. – Soheil Armin Nov 07 '19 at 18:19
  • Sure. Read section Bindings: https://doc.qt.io/qt-5/qtquick-performance.html - var doesn't allow optimized bindings. It is generally a good idea, to give as much information as possible to the engine, so it might chose more specialized and optimized routines. – derM - not here for BOT dreams Nov 07 '19 at 19:37
  • @derM I could not find anywhere stating that *"var doesn't allow optimized bindings"* on that document – Bersan Apr 27 '22 at 12:44
  • @Bersan It might be, that this has changed in the newer Qt versions. I am pretty sure, there was an issue. It is still on the best practice page https://doc.qt.io/qt-5/qtquick-bestpractices.html#type-safety but not explicitly for performane reasons. What remains is the performance hint, to always choose the best fitting type to avoid expensive casting. I'd still aply this to *var* beeing less close than e.g. *Item*. However I switched from Qt 3 years ago, sadly. – derM - not here for BOT dreams May 08 '22 at 08:43