QML中的动态重新定位对象在初始加载时失败

时间:2012-05-11 18:54:59

标签: qt qml

我正在尝试根据从模型中继承的数据动态重新生成转发器中生成的QML对象。

这就像一个魅力 - 一举一动。当第一次生成对象时,在状态的ParentChange对象进行更改后,它将自动重新分配给Repeater的父 。在QML查看器中运行以下QML文件,注意控制台消息的顺序以查看我所描述的内容。

在您点击每个对象后,它们的行为与预期一致。

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" } }
        }
    }

}

我想出了一种修复行为的方法,但它并不漂亮。 (请参阅注释掉的" Connections"上面的代码用于该修复)。

是否有一种更清洁/更少黑客的方式来完成我在这里尝试的同样的事情?

1 个答案:

答案 0 :(得分:3)

简单的方法是在您的代表下放置额外的Item。这将导致Repeater重新显示Item,并且您自己的代码会设置其子级的新父级Rectangle元素。像这样:

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" } }
        }
    }
}