一个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
// ...
}
}