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
       // ...
   }
}
相关推荐
Forget the Dream23 分钟前
设计模式之责任链模式
java·c++·设计模式·责任链模式
停止重构24 分钟前
【开源】低代码 C++程序框架,Linux多线程程序
c++·低代码·多线程·开源框架·云计算引擎
Duramentee27 分钟前
C++ 设计模式 十二:责任链模式 (读书 现代c++设计模式)
c++·设计模式·责任链模式
_GR32 分钟前
Qt开发⑧Qt的窗口_下_浮动窗口+对话框
开发语言·css·c++·qt·microsoft
萌の鱼43 分钟前
leetcode 3183. 达到总和的方法数量
数据结构·c++·算法·leetcode
Forget the Dream1 小时前
设计模式之代理模式
java·c++·设计模式·代理模式
攻城狮7号3 小时前
【第十节】C++设计模式(结构型模式)-Flyweight( 享元)模式
c++·设计模式·享元模式
Forget the Dream4 小时前
设计模式之享元模式
java·c++·设计模式·享元模式
溟洵8 小时前
【C/C++】理解C++内存与Linux虚拟地址空间的关系---带你通透C++中所有数据
linux·c语言·c++
Chandler2410 小时前
C++11 智能指针:unique_ptr、shared_ptr和weak_ptr 功能特性 模拟实现
开发语言·c++