Qt/QML DelegateModel基础用法示例

要理解 Qt Quick 中的 DelegateModel,需要从模型-视图架构的核心矛盾入手:如何高效管理数据与视图呈现的解耦,尤其是当同一数据需要在多个视图(列表/网格/卡片)中以不同形式展示时。
一、DelegateModel 是什么?
DelegateModel 是 Qt Quick 提供的模型-委托管理组件,本质是 QAbstractItemModel 的 QML 实现。它的核心目标是:
- •将模型数据与**视图委托(Delegate)**的渲染逻辑分离;
- •允许同一数据模型被多个视图共享,每个视图使用不同的委托样式;
- •内部管理委托的创建、回收与生命周期,优化滚动性能。
二、核心定位:解决什么问题?
传统 Qt Quick 开发中,若需让同一数据在多个视图中呈现不同样式,常见做法是为每个视图单独定义 ListModel + delegate,导致:
- •数据重复维护(多份
ListModel); - •数据同步困难(修改一处需同步多处);
- •性能浪费(重复创建委托实例)。
DelegateModel 解决了这些问题:
- •数据只存一份:多个 DelegateModel 实例可共享同一数据模型;
- •委托独立配置:每个 DelegateModel 可定义自己的
delegate,适配不同视图; - •自动同步更新:数据变化时,所有依赖该模型的视图都会收到通知。
三、核心结构与关键属性
DelegateModel 继承自 QAbstractItemModel,因此具备标准模型的接口(rowCount/data/roleNames)。其核心组成如下:
1. 模型数据(Model Data)
DelegateModel 的数据来源可以是:
- •内部的
ListModel(直接定义在model属性中); - •外部模型(通过
model属性绑定,比如FileSystemModel或自定义 C++ 模型)。
示例:定义包含媒体数据的 DelegateModel
DelegateModel {id: mediaModel // 核心 DelegateModel 实例// 1. 数据模型:内部 ListModel(可替换为外部模型)model: ListModel {ListElement { filePath: "file:///media/video1.mp4"; thumbnail: "qrc:/thumbs/video1.jpg";duration: "02:30";title: "Video 1"}ListElement { filePath: "file:///media/video2.mp4"; thumbnail: "qrc:/thumbs/video2.jpg";duration: "01:45";title: "Video 2"}}
}
2. 委托(Delegate)
delegate 属性定义了每个数据项的渲染逻辑,是一个 QML 组件。它通过 modelData 访问当前项的数据(或通过 model.roleName 访问自定义角色)。
示例:列表视图的委托(紧凑样式)
delegate: Rectangle {width: ListView.view.width - 20;height: 80;color: "#f0f0f0";radius: 4;// 通过 modelData 访问数据(或 model.filePath/model.title)Image { source: modelData.thumbnail; width: 60; height: 60; anchors.left: parent.left; anchors.verticalCenter: parent.verticalCenter; anchors.margins: 10}Column {anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter; anchors.margins: 10; spacing: 5Text { text: modelData.title; font.bold: true; font.pixelSize: 16 }Text { text: modelData.duration; font.pixelSize: 12; color: "#666" }}
}
四、关键特性:为什么选择 DelegateModel?
1. 多视图共享同一数据
同一 DelegateModel 实例可被多个视图(ListView/GridView/Repeater)使用,每个视图仅需指定自己的 delegate。
示例:同一模型在 ListView 和 GridView 中的不同呈现
// 共享数据模型的两个 DelegateModel(可选,也可直接用一个实例)
DelegateModel {id: listDelegateModelmodel: mediaModel.model // 共享 mediaModel 的数据delegate: ... // 列表紧凑样式
}DelegateModel {id: gridDelegateModelmodel: mediaModel.model // 共享数据delegate: Rectangle {width: 150; height: 150;color: "#eee";Image { source: model.thumbRole; width: 120; height: 120 }Text { text: model.titleRole; anchors.centerIn: parent }}
}// 主界面:ListView 使用 listDelegateModel
ListView { model: listDelegateModel; anchors.fill: parent }// 详情页:GridView 使用 gridDelegateModel
GridView { model: gridDelegateModel; cellWidth: 160; cellHeight: 160; anchors.fill: parent }
2. 动态切换委托
无需重建视图,只需修改 DelegateModel 的 delegate 属性,即可动态改变项的呈现样式。
示例:点击按钮切换列表/详细模式
Button {text: "切换详细模式"onClicked: {// 切换 DelegateModel 的委托mediaModel.delegate = detailedDelegate;}
}Component {id: detailedDelegateRectangle {width: ListView.view.width - 20;height: 120;// 更详细的布局...}
}
3. 委托生命周期管理
DelegateModel 内部维护委托回收池:
- •当项滚出视图时,委托不会被销毁,而是回收到池中;
- •下次需要渲染同类项时,直接从池中复用,避免频繁创建/销毁 QML 对象,提升滚动性能。
4. 数据与呈现完全解耦
数据模型(model)和委托(delegate)是独立的组件:
- •修改数据模型(如新增字段)无需调整委托(只需更新角色或
modelData访问逻辑); - •修改委托样式(如颜色/布局)无需改动数据模型。
五、进阶用法
1. 嵌套 DelegateModel(层级数据)
可将一个 DelegateModel 作为另一个的 model,实现树形结构(如文件夹/文件列表):
DelegateModel {id: rootModelmodel: ListModel {ListElement { name: "Videos"; type: "folder" }}delegate: Item {// 文件夹项:嵌套子 DelegateModelColumn {Text { text: model.name }ListView {model: rootModel.get(model.index).children // 子模型delegate: ... // 文件项委托}}}
}
2. 结合异步加载(图片/数据)
委托中可使用 AsyncImage 或 Loader 实现懒加载,避免阻塞主线程:
delegate: Rectangle {AsyncImage {source: model.thumbRole;width: 60; height: 60;// 加载失败时显示占位符onStatusChanged: if (status == Image.Error) source = "qrc:/placeholder.png"}
}
3. 自定义委托交互
委托中的交互逻辑(如点击/长按)可通过信号传递给 DelegateModel 或父组件:
delegate: Rectangle {onClicked: {mediaModel.selectItem(model.index); // 通知 DelegateModel 选中项}
}// DelegateModel 中处理选中逻辑
DelegateModel {function selectItem(index) {console.log("选中项:", model.get(index).title);}
}
六、与传统方式的对比
| 维度 | 传统方式 | DelegateModel 方式 |
|---|---|---|
| 数据维护 | 多视图需多份 ListModel | 单份数据模型,多视图共享 |
| 委托复用 | 每个视图单独定义 delegate | 同一模型可配置不同 delegate |
| 数据同步 | 需手动同步多模型 | 数据变化自动通知所有视图 |
| 性能 | 重复创建委托,滚动卡顿 | 委托回收池,性能更优 |
七、总结
DelegateModel 是 Qt Quick 中数据与呈现解耦的核心组件,通过封装模型数据和委托管理,解决了多视图共享数据的痛点。它的价值在于:
- •降低维护成本:数据只存一份,委托独立配置;
- •提升性能:委托回收池优化滚动体验;
- •增强灵活性:动态切换委托,适配不同场景。
参考资料:
- •Qt 官方文档:DelegateModel
- •Qt Quick 模型-视图编程:Model/View Programming

惠州大亚湾
