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{
    width: 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 {
            width: 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
            width: 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
                width: 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
            width: 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來訪問這些屬性


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM