QML之ListView

ListView 是 QML 中用于显示列表数据的高效组件,它只渲染当前可见的项目,非常适合显示大量数据。

基本用法

ListView {
    id: listView
    width: 200
    height: 300
    model: myModel
    spacing: 5
    clip: true
    
    // 滚动条
    ScrollBar.vertical: ScrollBar { }
    
    // 分组设置
    section {
        property: "category"
        delegate: sectionHeader
    }
    
    // 高亮设置
    highlight: Rectangle {
        color: "lightblue"
        radius: 3
    }
    
    // 项目模板
    delegate: ItemDelegate {
        width: ListView.view.width
        text: model.name
        highlighted: ListView.isCurrentItem
    }
    
    // 键盘导航
    Keys.onUpPressed: decrementCurrentIndex()
    Keys.onDownPressed: incrementCurrentIndex()
}

ListView 属性表

核心属性

属性 类型 默认值 说明
model variant - 数据模型 (数字/数组/ListModel/QAbstractItemModel)
delegate Component - 定义每个项目的可视化组件
currentIndex int -1 当前选中项的索引
count int - 只读,模型中的项目总数
spacing real 0 项目之间的间距

布局属性

属性 类型 默认值 说明
orientation enumeration ListView.Vertical 列表方向 (Vertical/Horizontal)
layoutDirection enumeration Qt.LeftToRight 布局方向 (LeftToRight/RightToLeft)
verticalLayoutDirection enumeration ListView.TopToBottom 垂直布局方向 (TopToBottom/BottomToTop)
header Component - 列表头部组件
footer Component - 列表尾部组件
headerPositioning enumeration ListView.InlineHeader 头部定位方式
footerPositioning enumeration ListView.InlineFooter 尾部定位方式

滚动属性

属性 类型 默认值 说明
contentWidth real - 只读,内容宽度
contentHeight real - 只读,内容高度
contentX real 0 水平滚动位置
contentY real 0 垂直滚动位置
flickableDirection enumeration Flickable.AutoFlickDirection 滚动方向
boundsBehavior enumeration Flickable.StopAtBounds 边界行为
flickDeceleration real 1500 滚动减速速率
maximumFlickVelocity real 2500 最大滚动速度
snapMode enumeration ListView.NoSnap 对齐模式
highlightRangeMode enumeration ListView.NoHighlightRange 高亮范围模式

分组属性 (section)

属性 类型 默认值 说明
section.property string - 分组依据的属性名
section.criteria enumeration ViewSection.FullString 分组标准
section.delegate Component - 分组标题组件
section.labelPositioning enumeration ViewSection.InlineLabels 分组标签位置

性能优化属性

属性 类型 默认值 说明
cacheBuffer int 0 预渲染区域大小(像素)
uniformItemSizes bool false 是否所有项目大小相同
reuseItems bool false (Qt6默认为true) 是否重用项目

视觉属性

属性 类型 默认值 说明
highlight Component - 当前选中项的高亮组件
highlightFollowsCurrentItem bool true 高亮是否跟随当前项
highlightMoveDuration int 150 高亮移动动画时长(ms)
highlightResizeDuration int 0 高亮大小调整动画时长(ms)
keyNavigationWraps bool false 键盘导航是否循环

信号

信号 说明
currentIndexChanged() 当前索引变化时触发
currentItemChanged() 当前项目变化时触发
contentXChanged() 水平滚动位置变化时触发
contentYChanged() 垂直滚动位置变化时触发

常用方法

方法 说明
positionViewAtIndex(index, mode) 滚动到指定索引
positionViewAtBeginning() 滚动到开头
positionViewAtEnd() 滚动到末尾
forceLayout() 强制重新布局
incrementCurrentIndex() 增加当前索引
decrementCurrentIndex() 减少当前索引

数据模型

1. 简单数字模型

qml

model: 10  // 生成0-9的索引

2. JavaScript数组

qml

model: ["Apple", "Banana", "Orange"]
// delegate中通过 modelData 访问
Text { text: modelData }

3. ListModel (动态模型)

qml

ListModel {
    id: myModel
    ListElement { name: "Alice"; age: 25 }
    ListElement { name: "Bob"; age: 30 }
}

ListView {
    model: myModel
    delegate: Text { text: name + ", " + age }
}

4. C++模型 (QAbstractItemModel)

qml

model: myCppModel  // 需要在C++中注册

高级功能

分组显示 (section)

qml

ListView {
    model: myModel
    section {
        property: "category"  // 分组依据的属性
        criteria: ViewSection.FullString
        delegate: Rectangle {
            width: parent.width
            height: 30
            color: "lightblue"
            Text { text: section; anchors.centerIn: parent }
        }
    }
}

添加页眉页脚

qml

ListView {
    header: Rectangle {
        width: parent.width
        height: 50
        color: "yellow"
        Text { text: "List Header"; anchors.centerIn: parent }
    }
    
    footer: Component {
        Rectangle {
            width: parent.width
            height: 50
            color: "orange"
            Text { text: "End of List"; anchors.centerIn: parent }
        }
    }
}

动态更新模型

qml

Button {
    text: "Add Item"
    onClicked: myModel.append({"name": "New", "age": 0})
}

Button {
    text: "Remove First"
    onClicked: myModel.remove(0)
}

交互功能

选择项高亮

qml

ListView {
    highlight: Rectangle {
        color: "lightblue"
        radius: 5
    }
    highlightFollowsCurrentItem: true
    focus: true
}

点击处理

qml

delegate: MouseArea {
    width: ListView.view.width
    height: 50
    onClicked: {
        ListView.view.currentIndex = index
        console.log("Clicked:", model.name)
    }
    // 内容...
}
 
 

性能优化

  1. 固定尺寸:为delegate设置明确的高度或使用uniformItemSizes: true

  2. 异步加载:对复杂delegate使用Loader

  3. 缓存:增加cacheBuffer预渲染不可见项目

  4. 简化delegate:减少嵌套层次

qml

ListView {
    cacheBuffer: 400  // 缓存额外200像素外的项目
    uniformItemSizes: true  // 所有项目大小相同
}
 
 

常见问题解决

1. 滚动条添加

qml

ListView {
    ScrollBar.vertical: ScrollBar { }
}

2. 滚动到指定位置

qml

// 滚动到末尾
positionViewAtEnd()

// 滚动到特定索引
positionViewAtIndex(10, ListView.Beginning)

3. 键盘导航

qml

ListView {
    focus: true
    Keys.onUpPressed: currentIndex--
    Keys.onDownPressed: currentIndex++
}

4. 下拉刷新实现

qml

ListView {
    header: RefreshHeader {
        refreshing: listModel.isRefreshing
        onRefresh: listModel.refreshData()
    }
}