QML---Repeater

repeater是用来重复创建同一类型组件的对象,嗯。。提到这个首先得知道QML的一些机制,提倡设计者让数据与模型分离开来,数据是数据模型是模型。repeater就可以根据数据,调用同一个模型去创建多个对象。直接举个例子吧

 import QtQuick 2.0

 Row {
     Repeater {
         model: 3
         delegate:Rectangle {
             width: 100; height: 40
             border.width: 1
             color: "yellow"
         }
     }
 }

这是QT帮助文档里面的代码 Row是一个布局器,只看repeater部分,这个是代表创建3个这样的rectangle。

model属性存放数据,可以是数字,也可以是数组,还可以是一个数据类型的对象

delegate属性存放模型,在repeater中,这个delegate属性名是可以省略的,直接写模型也是没问题的,这个模型会调用model的数据

通过repeater生成的对象如果想要访问的话就需要通过repeater的 Item itemAt(index) 函数进行访问

定义模型就不说了,这里具体讲的是数据的定义,一般数据分三种情况:

1.模型不需要数据,只需要指定个数

这种情况只需要将model给定一个数字,代表创建几个,就类似于开头例子那样

2.模型需要简单的数据,这个时候可以使用数组进行创建

这个时候数组的长度,就是创建的个数,数组的内容就是模型的数据,如下面的例子所示:

Repeater{
        id:id_repeater
        model: ["data1","data2"]
        Rectangle{
            width: 120
            height: 120
            color: "red"
            visible: index === 0
            Text {
                text: modelData
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                color: "black"
            }
        }
    }

这样就会创建两个内部有文字的rectangle,并且只有第一个字符为“data1”的才会显示,这里访问数据就用modelData去访问数据,如果想要特殊指定,比如第二个要隐藏,就可以在模型内部通过判断index去修改(index代表是这个repeater的第几个对象)

3.如果模型需要比较复杂的数据,单纯的数组就不能满足条件了,这个时候就需要用到数据对象了,比较常用的是listmodel,基本上listmodel能满足绝大部分要求了,至于listmodel怎么用可以看看帮助文档,下面是这类型的示例

ListModel{
        id:id_model
        ListElement{
            mName:"data1"
            mScrp:"test1"
        }
        ListElement{
            mName:"data2"
            mScrp:"test2"
        }
    }

    Repeater{
        id:id_repeater
        model: id_model
        Rectangle{
            width: 120
            height: 120
            color: "red"
            visible: index === 0
            Text {
                text: mName
                color: "black"
            }
            Text {
                text: mScrp
                color: "black"
            }
        }
    }

这个时候只需要将模型里面需要用到数据的地方写成对应的数据的名字,就能够进行访问了。

以上是它的基本用法,不多,但是基本都有需要注意的地方,这里才算是最重要的部分,了解到了这些在实际使用的时候会有大用处

第一二种需要注意的就是如果model的数组或者数字发生改变,那么repeater会销毁所有已经创建的对象再重新生成。数字改变很好理解,但是数组改变就有点复杂了。

数组改变:

1.数组内部值的改变,比如通过下标修改数组的值,这个时候虽然数组的下标值改变了,但是对repeater来说没有任何影响,甚至模型里面的数据都不会改变。

Repeater{
        id:id_repeater
        model: id_root.mData
        Rectangle{
            width: 120
            height: 120
            color: index === 1 ? "transparent" : "red"
            visible: index === 0
            Text {
                text: modelData
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                color: "black"
            }
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("clicked")
                    id_root.mData[0] = "changed"
                    console.log(mData)
                }
            }
        }
    }

这行代码执行时,数据是更改了,但是模型的显示还是以前的数据。

2.model如果是判断为更改了对象的操作,这个时候会将有值判定的过程,如果判定两个值相等那就不会重新构建,但是如果值不等,就会重新全部创建

property var mData: ["hello","world"]
    property var mData2: ["hello","world"]
    property var bFlag: true
    Repeater{
        id:id_repeater
        model: id_root.bFlag ? id_root.mData : id_root.mData2
        Rectangle{
            width: 120
            height: 120
            color: index === 1 ? "transparent" : "red"
            Text {
                text: modelData
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                color: "black"
            }
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("click")
                    id_root.bFlag = !id_root.bFlag
                }
            }
            Component.onCompleted: {
                console.log("create comp" + index)
            }
        }
    }

 qml: create comp0
qml: create comp1
qml: click
qml: click

除了最开始创建时打印,更改并不会重新创建

现在将另一个数组改个值

property var mData: ["hello","world"]
    property var mData2: ["hello","create"]
    property var bFlag: true
    Repeater{
        id:id_repeater
        model: id_root.bFlag ? id_root.mData : id_root.mData2
        Rectangle{
            width: 120
            height: 120
            color: index === 1 ? "transparent" : "red"
            Text {
                text: modelData
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                color: "black"
            }
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("click")
                    id_root.bFlag = !id_root.bFlag
                }
            }
            Component.onCompleted: {
                console.log("create comp" + index)
            }
        }
    }

 qml: create comp0
qml: create comp1
qml: click
qml: create comp0
qml: create comp1

可以发现每次点击都会重新创建对象 

如果是model的对象,那么它的改变就非常直观了,因为每个一串数据都会被当作一个对象,可以单独管理每一个模型,所以,只要model的数据串改变了那模型显示的数据就会 更改,并且不会重新创建对象,下面是一个示例

ListModel{
        id:id_model
        ListElement{
            mName:"data1"
            mScrp:"test1"
        }
        ListElement{
            mName:"data2"
            mScrp:"test2"
        }
    }

    Repeater{
        id:id_repeater
        model: id_model
        Rectangle{
            width: 120
            height: 120
            color: "red"
            visible: index === 0
            Text {
                text: mName
                color: "black"
            }
            Component.onCompleted: {
                console.log("create")
            }
        }
    }

    Timer {
        interval: 500; running: true; repeat: true
        onTriggered: {
            console.log("update")
            id_model.setProperty(0,"mName",Math.random().toString())
        }
    }

这个时候的打印

qml: create
qml: create
qml: update
qml: update
qml: update
qml: update

 发现只会更新但是并不会重新生成对象

你可能感兴趣的:(qml,qt,开发语言,c++)