QML学习十五:ListView的简单使用(内建Model)

若该文为原创文章,转载请注明原文出处

一、概念

1、MVC

作为一种经典的架构模式,通过把职责、性质相近的成分归结在一起,不相近的进行隔离,MVC将系统分解为模型、视图、控制器三部分,每一部分都相对独立,职责单一。MVC是对系统复杂性的一种合理的梳理与切分,它的思想实质就是“关注点分离”。

QT中的Model-View编程框架,对Controller部分做了改动,引入了Delegate的概念,合起来就是Model-View-Delegate。

在QT C++中,对Model-View-Delegate已经做了基础的实现,不必去设计Model-View框架,只需学习Qt给的框架即可。

2、ListView

ListView用来一个条目列表,条目对应的数据来自于Model, 而每个条目的外观则由Delegate决定。

要使用ListView,必须指定一个Model、一个Delegate。

Model可以是QML内建类型,如ListModel、XmlListModel,也可以是在C++实现的QAbstractItemModel或QAbstractListModel的派生类。

二、ListView简单的使用

1、简单的显示例子

修改main.qml内容:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import MyObj 1.0


Window {
    id: window
    visible: true
    width: 600
    height: 480
    title: qsTr("Hello World")

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

        Component {
            id: phoneDelegate

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

                MouseArea {
                    anchors.fill: parent
                    onClicked: wrapper.ListView.view.currentIndex = 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
                    }

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

                    Text {
                        text: manufacturer
                        color: wrapper.ListView.isCurrentItem ? "red" : "black";
                        font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                        Layout.fillWidth: true
                    }
                }
            }
        }

        ListView {
            id: listView
            anchors.fill: parent
            delegate: phoneDelegate

            model: ListModel {
                id: phoneModel

                ListElement {
                    name: "iPhone 3gs"
                    cost: "1000"
                    manufacturer: "Apple"
                }

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

                ListElement {
                    name: "iphone 5"
                    cost: "2800"
                    manufacturer: "Apple"
                }

                ListElement {
                    name: "iphone 6"
                    cost: "3800"
                    manufacturer: "Apple"
                }

                ListElement {
                    name: "iphone 8"
                    cost: "4800"
                    manufacturer: "Apple"
                }
            }
            focus: true
            highlight: Rectangle {
                color: "lightblue"
            }
        }
    }

}



编译运行:

 QML学习十五:ListView的简单使用(内建Model)_第1张图片

2、增加Head和Footer

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import MyObj 1.0


Window {
    id: window
    visible: true
    width: 600
    height: 480
    title: qsTr("Hello World")

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

        Component {
            id: phoneModel

            ListModel {
                ListElement {
                    name: "iPhone 3"
                    cost: "1000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 4"
                    cost: "2000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 5"
                    cost: "3000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 6"
                    cost: "4000"
                    manufacturer: "Apple"
                }
            }
        }

        Component {
            id: headerView

            Item {
                width: parent.width

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

        Component {
            id: footerView

            Text {
                width: parent.width
                font.italic: true
                color: "blue"
                height: 30
                verticalAlignment: Text.AlignVCenter
            }
        }

        Component {
            id: phoneDelegate

            Item {
                id: wrapper

                width: parent.width
                height: 30

                MouseArea {
                    anchors.fill: parent
                    onClicked: wrapper.ListView.view.currentIndex = 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
                    }

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

                    Text {
                        text: manufacturer
                        color: wrapper.ListView.isCurrentItem ? "red" : "black";
                        font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                        Layout.fillWidth: true
                    }
                }
            }
        }

        ListView {
            id: listView
            anchors.fill: parent
            delegate: phoneDelegate

            model: phoneModel.createObject(listView)
            header: headerView
            footer: footerView
            focus: true
            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 = "-";
                }
            }
        }
    }
}



编译结果:

QML学习十五:ListView的简单使用(内建Model)_第2张图片

 3、访问与修改Model

(1) 访问数据

ListModel的count属性表示Model中有多少条数据。

ListModel的get()方法接受一个int类型的参数,用来获取指定索引位置的数据返回一个QML对象。

然后,我们就可以像访问属性那样访问数据的role。

eq:

var data = listView.model.get(listView.currentIndex);
console.log(data.name + "," + data.cost + "," + data.manufacturer);

(2) 删除数据

ListModel的remove(int index, int count)方法,删除一条或多条数据。

eq:

MouseArea {
    anchors.fill: parent
    onClicked: {
        wrapper.ListView.view.currentIndex = index;
    }

    onDoubleClicked: {
        wrapper.ListView.view.model.remove(index);
    }
}

(3) 修改数据

修改数据使用的是ListModel的setProperty(int index, string property, variant value)方法。

比如:修改价格
listView.model.setProperty(5, "cost", 16999)

(4) 添加数据

添加数据使用的是append()方法。

eq:
listView.model.append (
    {
        "name" : "mx3"
        "cost" : "1978"
        "manufacturer" : "Meizu"
    }
)

三、完整代码

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import MyObj 1.0


Window {
    id: window
    visible: true
    width: 600
    height: 480
    title: qsTr("Hello World")

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

        Component {
            id: phoneModel

            ListModel {
                ListElement {
                    name: "iPhone 3"
                    cost: "1000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 4"
                    cost: "2000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 5"
                    cost: "3000"
                    manufacturer: "Apple"
                }
                ListElement {
                    name: "iPhone 6"
                    cost: "4000"
                    manufacturer: "Apple"
                }
            }
        }

        Component {
            id: headerView

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

        Component {
            id: footerView

            Item {
                id: footerRootItem

                width: parent.width
                height: 30
                property alias text: txt.text
                signal clean()
                signal add()

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

                Button {
                    id: clearAll

                    anchors.right: parent.right
                    anchors.verticalCenter: parent.verticalCenter
                    text: "Clear"
                    onClicked: footerRootItem.clean();
                }

                Button {
                    id: addOne

                    anchors.right: clearAll.left
                    anchors.rightMargin: 4
                    anchors.verticalCenter: parent.verticalCenter
                    text: "Add"
                    onClicked: footerRootItem.add()
                }
            }
        }

        Component {
            id: phoneDelegate

            Item {
                id: wrapper

                width: parent.width
                height: 30

                MouseArea {
                    anchors.fill: parent
                    onClicked: wrapper.ListView.view.currentIndex = 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
                    }

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

                    Text {
                        text: manufacturer
                        color: wrapper.ListView.isCurrentItem ? "red" : "black";
                        font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
                        Layout.fillWidth: true
                    }
                }
            }
        }

        ListView {
            id: listView
            anchors.fill: parent
            delegate: phoneDelegate

            model: phoneModel.createObject(listView)
            header: headerView
            footer: footerView
            focus: true
            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 addOne() {
                model.append(
                            {
                                "name" : "MX3",
                                "cost": "1233",
                                "manufacturer": "Meizu"
                            });
            }

            Component.onCompleted: {
                listView.footerItem.clean.connect(listView.model.clear);
                listView.footerItem.add.connect(listView.addOne);
            }
        }
    }
}



编译结果:

QML学习十五:ListView的简单使用(内建Model)_第3张图片

 

如有侵权,请及时联系博主删除,VX:18750903063

你可能感兴趣的:(QT之QML,学习)