(九)ListView

Qt中的Model-View编程框架,对Controller部分做了改动,引入了Delegate的概念,合起来就是Model-View-Delegate,Model负责提供数据,View负责提供布局管理和Item创建,样式由Delegate负责。

ListView

ListView用来显示一个条目列表,条目对应的数据来自于Model,而每个条目的外观则有Delegate决定。要使用ListView,必须为其指定一个Model,一个Delegate。Model可以是QML内建类型,如ListModel、XmlListModel,也可以是C++中实现的QAbstractItemModel或QAbstractListModel的派生类。

import QtQuick 2.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
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 4s";
                cost: "2300";
                manufacturer: "Apple";
            }
            ListElement {
                name: "IPhone 5";
                cost: "4900";
                manufacturer: "Apple";
            }
            ListElement {
                name: "xiao mi 2s";
                cost: "1900";
                manufacturer: "XiaoMi";
            }
            ListElement {
                name: "OnePlus 3T";
                cost: "2700";
                manufacturer: "OnePlus";
            }
            ListElement {
                name: "IQOO";
                cost: "2100";
                manufacturer: "VIVO";
            }
        }

        focus: true;
        highlight: Rectangle {
            color: "lightblue";
        }
    }
}

在ListView对象中,使用ListModel对象充当ListView的model,在ListModel中,ListElement 代表一条数据。ListElement中的每一条数据都称为role,每一条数据都由role-name:role-value构成,role-name必须以小写字母开头,role-value必须时简单的常量,例如字符串、布尔值、数字或者枚举类型。在ListElement中定义的role,可以在Delegate中通过role-name来访问。
ListView的delegate属性类型为Component,id为phoneDelegate,phoneDelegate的顶层元素是Row,Row内嵌三个Text对象来展示Model定义的ListElementd的三个role。ListView暴露给delegate一个index属性,代表当前delegate实例对应的Item的索引位置。
示例中选中条目有一个浅蓝色背景,它由ListView的highlight属性初始化一个Rectangle来定义高亮北京
在这里插入图片描述

header

通过为ListView的header属性设置一个Component,ListView就可以显示自定义的表头

import QtQuick 2.2
import QtQuick.Controls 1.2
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: "IPhone 5";
                cost: "4900";
                manufacturer: "Apple";
            }
            ListElement {
                name: "xiao mi 2s";
                cost: "1900";
                manufacturer: "XiaoMi";
            }
            ListElement {
                name: "OnePlus 3T";
                cost: "2700";
                manufacturer: "OnePlus";
            }
            ListElement {
                name: "IQOO";
                cost: "2100";
                manufacturer: "VIVO";
            }
        }
    }

    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: 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;
        focus: true;
        highlight: Rectangle {
            color: "lightblue"
        }
    }
}

ListView的delegate、model、header三个属性均由Component构成
在这里插入图片描述

footer

footer属性允许我们指定ListView的页脚,footerItem保存了footer组件常见出来的Item对象,这个Item会被添加到ListView的末尾,在所有可见的Item之后。

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

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

onCurrentIndexChanged信号没有参数,只在当前条目选择变化时触发。
在这里插入图片描述

访问与修改Model

ListModel的count属性表示Model中有多少条数据,dynamicRoles属性为true时表示Model中的role对应的值可以修改,默认为false,不过要注意的是,一旦你使用了dynamicRoles,ListModel的性能会大大下降,通常它带来的性能损失是使用静态类型的4-6倍。
(1)访问数据
ListModel的get()方法用来获取指定索引位置的数据,返回一个QML对象,然后可以用这个QML对象访问数据的role了:

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

(2)删除数据
如果你想删除一条或多条数据,可以使用ListModel的remove(int index,int count)方法。清空一个model直接调用clear()方法。
将上面的phoneDelegate修改一下:实现双击删除一条数据

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

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

修改一下footer组件,添加一个清除按钮,用来清除所有数据:

Component {
     id: footerView;
     Item {
        id: footerRootItem;
        width: parent.width;
        height: 30;
        signal clean();

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

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

给ListView添加Component.onCompleted附加信号处理器:

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

(3)修改数据
想要修改Model的数据,可以使用ListModel的setProperty(int index, string property, variant value)方法:

listView.model.setProperty(5, "cost", 18888);

如果想替换某一条数据,可以使用set(int index, jsobject dict)方法,我们经常用对象的字面量表示法构造一个对象传递给set()方法:

listView.model.set(0, {"name":"iqooneo", "cost":2099, "manufacturer": "vivo"});

(4)添加数据
向model的尾部添加数据,使用append()方法:

listView.model.append(
	{
		"name" : "xiaomi",
		"cost" : "2699",
		"manufacturer" : "xiaomi"
	}
);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vegetablesssss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值