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
       // ...
   }
}
相关推荐
悲伤小伞17 分钟前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
小灰灰搞电子27 分钟前
Qt实现Android的图案密码(图形解锁)源码分享
开发语言·qt
m0_675988231 小时前
Leetcode3218. 切蛋糕的最小总开销 I
c++·算法·leetcode·职场和发展
code04号4 小时前
C++练习:图论的两种遍历方式
开发语言·c++·图论
煤泥做不到的!6 小时前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
axxy20006 小时前
leetcode之hot100---24两两交换链表中的节点(C++)
c++·leetcode·链表
若亦_Royi7 小时前
C++ 的大括号的用法合集
开发语言·c++
ragnwang11 小时前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
kiiila11 小时前
【Qt】对象树(生命周期管理)和字符集(cout打印乱码问题)
开发语言·qt