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
       // ...
   }
}
相关推荐
誓约酱20 分钟前
(动画)Qt控件 QLCDNumer
开发语言·c++·git·qt·编辑器
@小博的博客31 分钟前
C++初阶学习第十三弹——容器适配器和优先级队列的概念
开发语言·数据结构·c++·学习
离歌漠35 分钟前
C#调用C++ DLL方法之P/Invoke
c++·c#·p/invoke
xiaowu08036 分钟前
MFC线程-通过CWinThread派生类实现
c++·mfc
sheng12345678rui43 分钟前
mfc100u.dll是什么?分享几种mfc100u.dll丢失的解决方法
游戏·microsoft·电脑·dll修复工具·1024程序员节
兵哥工控43 分钟前
MFC工控项目实例三十一模拟量转化为工程量
c++·mfc
zaim11 小时前
计算机的错误计算(一百六十三)
java·c++·python·matlab·错数·等价算式
敲键盘的老乡1 小时前
堆优化版本的Prim
数据结构·c++·算法·图论·最小生成树
码农多耕地呗1 小时前
trie树-acwing
数据结构·c++·算法
daily_23332 小时前
数据结构——小小二叉树第三幕(链式结构的小拓展,二叉树的创建,深入理解二叉树的遍历)超详细!!!
数据结构·c++·算法