Search code examples
qtqmlrepeater

How to move/animate components created by repeater in QML?


I have a component named Tile in Tile.qml, which I want to create by a Repeater. Tile.qml is as follows:

import QtQuick 2.0

Rectangle {
    id: tile

    property string tileLabel: label.text
    property int tileSize: height

    width: 50
    height: tileSize
    color: "green"
    border.color: Qt.lighter(color)
    anchors.bottom: parent.bottom

    Text {
        id: label
        color: "white";
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.bottom
        text: tileLabel
    }
}

And my main.qml is as follows:

import QtQuick 2.0

Rectangle {
    id: root
    width: 552; height: 300
    color: "#3C3C3C"
    border.color: Qt.lighter(color)

    Row {
        id: tilesRow
        anchors.margins: 8
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        spacing: 4
        Repeater {
            id: repeater
            model: 10
            delegate: Tile {
                tileSize: Math.random() * 100 + 1
                tileLabel: tileSize
            }
        }
    }

    Rectangle {
        id: button
        width: 100
        height: 30
        color: "gray"
        focus: true

        Text {
            anchors.centerIn: parent
            color: "white"
            text: "Button"
        }
        MouseArea {
            hoverEnabled: true
            anchors.fill: parent
            onEntered: { button.color = Qt.lighter("blue")}
            onExited: { button.color = "gray" }
            onPressed: { button.color = "blue" }
            onReleased: { button.color = Qt.lighter("blue") }
            onClicked: func()
        }
    }
}

I need to sort the tiles when the button is clicked so that the tiles are in ascending order by their labels. I can access the labels of the tiles using repeater.itemAt(i).tileSize. How can I animate the movement of tiles as they are moved/swapped?


Solution

  • Small example:

    import QtQuick 2.3
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 800
        height: 600
    
        Row {
            anchors.centerIn: parent
            property var word: ['H','e','l','l','o','!']
            id: row
            Repeater {
                id: repeater
                model: row.word.length
                delegate: Rectangle {
                    id: delegate;
                    width: 100
                    height: 100
                    property int pos
                    color: Qt.rgba(Math.random(),Math.random(),Math.random(),1);
                    Text {
                        anchors.centerIn: parent
                        font.pixelSize: 36
                        color: "white"
                        text: row.word[index]
                    }
    
                    Behavior on x {
                        ParallelAnimation {
                            PropertyAnimation {
                                duration: 500
                                easing.type: Easing.InOutBack
                            }
                            SequentialAnimation {
                                PropertyAnimation {
                                    target: delegate
                                    property: "y"
                                    from: 0
                                    to: delegate.pos == 1 ? 20 : -20
                                    duration: 250
                                }
                                PropertyAnimation {
                                    target: delegate
                                    property: "y"
                                    from: delegate.pos == 1 ? 20 : -20
                                    to: 0
                                    duration: 250
                                }
                            }
                        }
                    }
                    Behavior on rotation {
                        RotationAnimation {
                            direction: RotationAnimation.Clockwise
                            duration: 300
                        }
                    }
                }
            }
        }
    
        Timer {
            interval: 1000
            running: true
            repeat: true
            onTriggered: {
                var element1 = repeater.itemAt(Math.round(Math.random() * (repeater.count - 1)));
                var element2 = repeater.itemAt(Math.round(Math.random() * (repeater.count - 1)));
                if(element1 === element2) {
                    element1.rotation = element1.rotation + 90;
                } else {
                    element1.pos = 1;
                    element2.pos = 2;
                    var temp = element1.x;
                    element1.x = element2.x;
                    element2.x = temp;
                }
            }
        }
    }