qml----Model/View入门(一)listview

在SmallTalk中有一个经典的设计模式-MVC。即模型-视图-控制器,在qml中将control改成了delegate(委托),也就是现在的Model-View-Delegate.换了个说法,Model还是负责数据,View管着视图输出,Delegate呢就是一个介于视图和数据之间的桥梁。

下面先来看个例子,效果图如下:

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1

Rectangle{
     360
    height: 300
    color: "#EEEEEE"

    Component{
        id: phoneModel

        ListModel{
            ListElement{
                name: "iphone 3GS"
                cost: "1000"
                manufacturer: "Apple"
            }

            ListElement{
                name: "iphone 4"
                cost: "1800"
                manufacturer: "Apple"
            }

            ListElement{
                name: "iphone 4s"
                cost: "2300"
                manufacturer: "Apple"
            }

            ListElement{
                name: "iphne 5"
                cost: "1590"
                manufacturer: "Apple"
            }

            ListElement{
                name: "iphone B199"
                cost: "1590"
                manufacturer: "HuaWei"
            }

            ListElement{
                name: "MI 25"
                cost: "1999"
                manufacturer: "XiaoMi"
            }

            ListElement{
                name: "GALAXY s5"
                cost: "4698"
                manufacturer: "Samsung"
            }
        }
    }//phoneModel is end(视图数据)

    Component{
        id: headView
        Item {
             parent.width
            height: 30
            RowLayout{
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                spacing: 8
                Text{
                    text: "name"
                    font.bold: true
                    font.pixelSize: 20
                    Layout.preferredWidth: 120
                }

                Text{
                    text: "cost"
                    font.bold: true
                    font.pixelSize: 20
                    Layout.preferredWidth: 80
                }

                Text{
                    text: "manufacturer"
                    font.bold: true
                    font.pixelSize: 20
                    Layout.fillWidth: true
                }
            }
        }
    }//headview is end(定义的表头)

    Component{
        id: footerView

        Item{
            id: footerRootItem
             parent.width
            height: 30
            property alias text: txt.text
            signal clean()
            signal change()
            signal replace()

            Text{
                id: txt
                anchors.left: parent.left
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                 parent.width/4
                font.italic: true
                color: "blue"
                verticalAlignment: Text.AlignVCenter
            }

            Button{
                id: cleanBtn
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                text: "clear"
                onClicked: footerRootItem.clean()
            }//清空视图数据的按钮

            Button{
                id: changeBtn
                anchors.right: cleanBtn.left
                anchors.rightMargin:  5
                anchors.verticalCenter: parent.verticalCenter
                text: "change data"
                onClicked: footerRootItem.change()
            }//改变选中行数据

            Button{
                id: replaceBtn
                anchors.right: changeBtn.left
                anchors.rightMargin: 5
                anchors.verticalCenter: parent.verticalCenter
                text: "replace data"
                onClicked: footerRootItem.replace()
            }//替换选中行的数据
        }

    }//footer属性允许我们制定listview的页脚,footerItem保存了footer组件创建出来的item对象,这个item会被
    //添加到listview的末尾,在所有可见的item之后

    Component{
        id: phoneDelegate
        Item {
            id: wrapper
             parent.width
            height: 30

            MouseArea{
                anchors.fill: parent
                onClicked: wrapper.ListView.view.currentIndex = index
                onDoubleClicked: wrapper.ListView.view.model.remove(index)
            }

            RowLayout{
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                spacing: 8
                Text{
                    id: coll
                    text: name
                    color: wrapper.ListView.isCurrentItem ? "red" : "black"
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                    Layout.preferredWidth: 120
                }//coll text is end

                Text{
                    text: cost
                    color: wrapper.ListView.isCurrentItem ? "red" : "black"
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                    Layout.preferredWidth: 80
                }//cost text is end

                Text{
                    text: manufacturer
                    color: wrapper.ListView.isCurrentItem ? "red" : "black"
                    font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                    Layout.fillWidth: true
                }//manufacturer is end
            }
        }
    }//delegate is end(视图的委托)

    ListView{
        id: listView
        anchors.fill: parent
        focus: trues
        delegate: phoneDelegate
        model: phoneModel.createObject(listView)
        header: headView
        footer: footerView
        highlight: Rectangle{
            color: "lightblue"
        }

        onCurrentIndexChanged: {
            if(listView.currentIndex >= 0){
                var data = listView.model.get(listView.currentIndex)
                listView.footerItem.text = data.name + "," + data.cost + "," + data.manufacturer
            }
            else
                listView.footerItem.text = " "
        }

        function changeItem()//修改模型数据
        {
            listView.model.setProperty(listView.currentIndex, "manufacturer", "China")
        }

        function replaceItem()//替换模型数据
        {
            listView.model.set(listView.currentIndex, {"name": "234 ninbi",                                                    "cost": 1999, "manufacturer": "ZhongXing"})
        }

        Component.onCompleted: {
            listView.footerItem.clean.connect(listView.model.clear)//关联信号
            listView.footerItem.change.connect(listView.changeItem)//关联改变信号
            listView.footerItem.replace.connect(listView.replaceItem)
        }
    }//定义listview
}
View Code
这个例子比较简单,增加了头和footer。另外,在下面放了几个按钮,用以演示对数据的修改和删除。如果要实现插入数据,那么需要在footerView中添加signal insert()

 ,并添加Button

Button{         id: insertOne
                anchors.right: addOne.left
                anchors.leftMargin: 4
                anchors.verticalCenter: parent.verticalCenter
                text: "Insert"
                onClicked: footerRootItem.insert()
            }

并且在 listView中实现Insert函数、建立与footerView的信号链接

 function addOne()
        {
            model.append(
                {
                    "name": "MX5",
                    "cost": "1899",
                    "manufacture" : "MeiZu"
                }
            )
        }

        function insertOne()
        {
            model.insert(Math.round(Math.random() * model.count),
               {
                    "name" : "HTC One E8",
                    "cost" : "2900",
                    "manufacture" : "HTC"
               }
            )
        }

        Component.onCompleted: {
            listView.footerItem.add.connect(listView.addOne)
            listView.footerItem.insert.connect(listView.insertOne)
        }

注意虽然delegate有很多附加属性以及信号等,但是只有顶层的item才能直接使用这些属性,
非顶层的item需要通过顶层item的id来访问这些属性

原文地址:https://www.cnblogs.com/SaveDictator/p/8192391.html