QML列表视图 ListView的使用

一个ListView可以显示来自由如ListModel和XmlListModel等内置 QML 类型创建的模型的数据,也可以用在 C++ 中定义的、继承自QAbstractItemModel或QAbstractListModel的自定义模型类的数据。

一个ListView要有一个模型,它定义了要显示的数据,还有一个委托,它定义了数据应该如何显示。ListView中的项可以水平或垂直布局。由于ListView继承自Flickable,所以列表视图也是可滑动的。

1. 简单使用

下面定义一个简单的数据模型(ListModel)和代理(本示例程序用Text),并用ListView来展示:

css 复制代码
// 数据模型
ListModel {
    id: cusModel

    ListElement {
        name: "Tom"
        number: "11111"
    }

    ListElement {
        name: "Jerry"
        number: "22222"
    }

    ListElement {
        name: "Spike"
        number: "33333"
    }
}

ListView {
    id: view
    model: cusModel    // 指定模型
    width: 200
    height: parent.height

    delegate: Text {    // 自定义代理
        text: name + " -> " + number
    }
}

运行结果图如下:

2. 自定义代理

由于上述例子的代理仅仅是一个Text,实属太难看;下面我们将代理改良下,让它变得稍微好看点:

css 复制代码
// 自定义代理项
Component {
    id: cusDelgate
    
    Item {
        width: 180
        height: 40

        Column {
            Text { text: '<b>名称:</b>' + name; color: "red";}
            Text { text: '<b>代号:</b> ' + number }
        }
    }
}

ListView {
    id: view
    model: cusModel  // 指定模型
    x: 20
    y: 20
    width: 200
    height: parent.height

    highlight: Rectangle { color: "lightsteelblue"; radius: 5 } // 高亮
    delegate: cusDelgate
    focus: true      // 设置为true则可以使用键盘上下键切换项,被选择的项以高亮显示

    // 框出ListView区域
    Rectangle {
        anchors.fill: parent
        color: "transparent"
        border.width: 1
        border.color: "black"
    }
}

运行结果如下图:
ListView比较常用的一些属性:

bash 复制代码
orientation: ListView.Horizontal (默认为ListView.Vertical)
header  // 自定义列表标头(页眉)
footer  // 自定义页脚
spacing // 项与项之间间距
... 更多详细请参考Qt帮助文档

3.使用ListView写一个简单的联系人列表

运行结果如下图:

ListView主要代码:

cpp 复制代码
ListView {
    id: listView
    width: 270
    model: 10
    clip: true

    anchors {
        top: parent.top
        left: parent.left
        bottom: parent.bottom
    }

    header: SearchBox {
        width: listView.width
    }

    delegate: ContactItem {
        id: contact
        width: listView.width
        height: 70
    }

    footer: Rectangle {
        id: footerRect
        width: ListView.view.width
        height: 30
        color: "lightblue"
        border.width: 1

        Text {
            anchors.centerIn: footerRect
            color: "red"
            text: "一共有 " + listView.count + " 项"
        }
    }
}

SearchBox代码:

cpp 复制代码
import QtQuick 2.15
import QtQuick.Controls 2.15

Rectangle {
    id: root
    height: 85

    TextField {
        id: search
        width: 100
        color: "transparent"
        leftPadding: 40
        placeholderText: "搜索"
        font.pixelSize: 20

        anchors {
            fill: parent
            margins: 20
        }

        background: Rectangle {
            anchors.fill: parent
            border.width: 1
            border.color: "gray"
            color: "transparent"
            radius: width / 2

            Image {
                id: name
                x: 10
                y: (parent.height - height) / 2
                width: 20
                height: 20
                source: "qrc:/images/icon/search.svg"
            }
        }
    }
}

ContactItem代码:

cpp 复制代码
import QtQuick 2.15
import QtQuick.Controls 2.15

Rectangle {
    id: root
    clip: true

    property bool selected: false       // 被选中
    onSelectedChanged: {
        if(selected) selectRect.width = 5
        else selectRect.width = 0
    }

    Component.onCompleted: {
        root.selected = true
    }

    // 分割线
    Rectangle {
        id: line
        color: "gray"
        width: parent.width
        height: 1
    }

    // 被选中时的状态矩形
    Rectangle {
        id: selectRect
        width: 10
        height: parent.height
        color: "blue"

        Behavior on width {
            PropertyAnimation {duration: 70}
        }
    }

    // 头像图片
    Rectangle {
        id: headImg
        width: parent.height - line.height
        height: width

        anchors {
            top: line.bottom
            left: selectRect.right
            leftMargin: 8
        }

        CusMaskShape {
            anchors.fill: parent
        }
    }

    // 名称及个性签名
    Column {
        id: txt
        height: parent.height

        anchors {
            left: headImg.right
            leftMargin: 10
            right: headImg.left
            top: line.top
            topMargin: {
                let topM = nameTxt.font.pixelSize + descTxt.font.pixelSize
                topM = (root.height - topM - line.height) / 2
                return topM;
            }
        }

        Text {
            id: nameTxt
            font.pixelSize: 20
            font.bold: true
            text: "Tom"
        }

        Text {
            id: descTxt
            font.pixelSize: 16
            font.bold: true
            text: "talk is cheap, show me the code!"
            color: "gray"
            elide: Text.ElideRight
        }
    }
}

4. 注意事项:

当要在代理中访问视图的属性时,最好不要使用父类属性绑定,例如:

css 复制代码
ListView {
   id: listView
   // ...

   delegate: Item {
       // 不建议
       width: parent.width

       // 推荐
       width: listView.width
       width: ListView.view.width
       // ...
   }
}
相关推荐
尘佑不尘19 分钟前
shodan5,参数使用,批量查找Mongodb未授权登录,jenkins批量挖掘
数据库·笔记·mongodb·web安全·jenkins·1024程序员节
LaoZhangGong12319 分钟前
使用常数指针作为函数参数
c++·经验分享
边疆.20 分钟前
C++类和对象 (中)
c语言·开发语言·c++·算法
yy_xzz22 分钟前
QT编译报错:-1: error: cannot find -lGL
开发语言·qt
SeniorMao0071 小时前
结合Intel RealSense深度相机和OpenCV来实现语义SLAM系统
1024程序员节
网安_秋刀鱼1 小时前
CSRF防范及绕过
前端·安全·web安全·网络安全·csrf·1024程序员节
WW、forever1 小时前
【ArcGIS Pro实操第4期】绘制三维地图
1024程序员节
记录学习-python1 小时前
Django-cookie,session
1024程序员节
b21431241 小时前
【运动的&足球】足球运动员球守门员裁判检测系统源码&数据集全套:改进yolo11-DBBNCSPELAN
1024程序员节
聪明的墨菲特i2 小时前
Vue组件学习 | 二、Vuex组件
前端·vue.js·学习·前端框架·1024程序员节