前言
Qt版本:6.8.0
作用
QIdentityProxyModel
是 Qt 模型/视图框架中的一个代理模型类,其核心作用是在不修改源模型结构和数据的前提下,作为中间层对源模型进行扩展或拦截操作。
1. 透明传递模型结构
- 直接映射源模型:默认情况下,
QIdentityProxyModel
的索引、行、列、父节点等结构与源模型完全一致。它不会对源模型的结构(如层级、行列数)做任何修改。 - 自动同步变更:当源模型发生数据或布局变化时(如插入行、修改数据),代理模型默认会自动转发这些变化到视图(可通过 Qt 6.8+ 的标志控制是否自动处理)。
2. 扩展或拦截数据
- 修改数据表现:通过重写
data()
或setData()
方法,可以拦截对数据的读写请求,例如:- 格式化数据显示(如日期、货币)。
- 动态计算派生数据(如显示某列的统计值)。
- 权限控制(根据用户角色隐藏敏感数据)。
- 添加元信息:通过
headerData()
重写,可以修改表头信息,或在role
参数中返回自定义角色数据。
3. 监听模型事件
- 监控源模型变化:通过连接源模型的信号(如
dataChanged
、rowsInserted
),可以在代理模型中实现自定义逻辑,例如:- 记录数据变更日志。
- 触发业务逻辑(如数据验证、自动保存)。
- 拦截操作:重写
insertRows()
、removeColumns()
等方法,可以在增删改操作前后添加额外逻辑(如弹窗确认)。
4. 优化性能(Qt 6.8+)
- 手动控制更新:通过
setHandleSourceDataChanges(false)
和setHandleSourceLayoutChanges(false)
,可以禁用代理模型对源模型变化的自动响应。这在以下场景有用:- 批量操作时减少不必要的更新。
- 自定义更高效的同步机制。
5. 作为其他代理模型的基础
- 构建复杂代理链:
QIdentityProxyModel
可以作为多层代理模型的基础层。例如:- 第一层代理修改数据格式。
- 第二层代理(如
QSortFilterProxyModel
)进行排序过滤。 - 每层代理各司其职,互不干扰。
典型应用场景
-
数据格式化
将源模型的原始数据(如时间戳)转换为用户友好的字符串。QVariant MyProxyModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole && index.column() == 2) { // 将时间戳转为日期格式 return QDateTime::fromSecsSinceEpoch(sourceModel()->data(index).toInt()).toString(); } return QIdentityProxyModel::data(index, role); }
-
权限控制
根据用户角色隐藏或禁用某些数据。QVariant MyProxyModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole && !hasPermission(index)) { return "*****"; // 隐藏敏感数据 } return QIdentityProxyModel::data(index, role); }
-
数据校验
在用户编辑数据时进行实时校验。bool MyProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!isValid(value)) { showError("Invalid input!"); return false; } return QIdentityProxyModel::setData(index, value, role); }
与其他代理模型的对比
代理模型 | 核心功能 | 适用场景 |
---|---|---|
QIdentityProxyModel | 保持结构不变,扩展或拦截数据/操作 | 数据格式化、权限控制、监听 |
QSortFilterProxyModel | 动态排序和过滤数据 | 表格排序、搜索过滤 |
QTransposeProxyModel | 转置行列(行变列,列变行) | 行列互换显示 |
它适用于需要在不影响底层模型的情况下,对数据展示、操作拦截或事件监听进行增强的场景。
函数
构造函数与析构函数
-
QIdentityProxyModel(QObject *parent = nullptr)
- 作用: 构造函数,创建一个
QIdentityProxyModel
实例。 - 参数:
parent
: 父对象指针,用于对象树的内存管理。
- 返回值: 无。
- 作用: 构造函数,创建一个
-
virtual ~QIdentityProxyModel()
- 作用: 虚析构函数,确保对象销毁时正确释放资源。
控制标志函数(Qt 6.8+)
-
bool handleSourceDataChanges() const
- 作用: 返回代理模型是否自动处理源模型的数据变更(如
dataChanged
信号)。 - 返回值:
true
表示代理自动处理数据变更;false
需手动处理。
- 作用: 返回代理模型是否自动处理源模型的数据变更(如
-
bool handleSourceLayoutChanges() const
- 作用: 返回代理模型是否自动处理源模型的布局变更(如
layoutChanged
信号)。 - 返回值:
true
表示代理自动处理布局变更;false
需手动处理。
- 作用: 返回代理模型是否自动处理源模型的布局变更(如
-
void setHandleSourceDataChanges(bool b)
- 作用: 设置是否自动处理源模型的数据变更(受保护函数,需在子类中调用)。
- 参数:
b
为true
启用自动处理。
-
void setHandleSourceLayoutChanges(bool b)
- 作用: 设置是否自动处理源模型的布局变更(受保护函数)。
- 参数:
b
为true
启用自动处理。
重写的公共函数
-
int columnCount(const QModelIndex &parent = QModelIndex()) const override
- 作用: 返回父索引下的列数,默认直接调用源模型的
columnCount()
。 - 参数:
parent
: 父索引,默认为根索引。
- 返回值: 列数。
- 作用: 返回父索引下的列数,默认直接调用源模型的
-
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
- 作用: 处理拖放操作的数据,默认转发到源模型。
- 参数:
data
: 拖放的 MIME 数据。action
: 拖放动作(如复制、移动)。row
,column
,parent
: 拖放目标位置。
- 返回值: 操作是否成功。
-
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
- 作用: 返回表头数据,默认调用源模型的
headerData()
。 - 参数:
section
: 表头段号(行或列)。orientation
: 横向(Qt::Horizontal
)或纵向(Qt::Vertical
)。role
: 数据角色(如显示文本、对齐方式)。
- 返回值: 表头数据。
- 作用: 返回表头数据,默认调用源模型的
-
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
- 作用: 创建代理模型的索引,默认直接映射到源模型的索引。
- 参数:
row
,column
: 行号和列号。parent
: 父索引。
- 返回值: 代理模型的索引。
-
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
- 作用: 插入列到代理模型,默认转发到源模型。
- 参数:
column
: 插入起始列。count
: 插入列数。parent
: 父索引。
- 返回值: 是否成功。
-
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
- 作用: 插入行到代理模型,默认转发到源模型。
- 参数: 类似
insertColumns
。
-
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
- 作用: 将源模型索引转换为代理模型索引。由于结构相同,直接返回
sourceIndex
。 - 参数:
sourceIndex
源模型索引。 - 返回值: 对应的代理模型索引。
- 作用: 将源模型索引转换为代理模型索引。由于结构相同,直接返回
-
QItemSelection mapSelectionFromSource(const QItemSelection &selection) const override
- 作用: 将源模型的选择转换为代理模型的选择。直接映射。
- 参数:
selection
源模型的选择范围。 - 返回值: 代理模型的选择范围。
-
QItemSelection mapSelectionToSource(const QItemSelection &selection) const override
- 作用: 将代理模型的选择转换为源模型的选择。直接映射。
- 参数:
selection
代理模型的选择。 - 返回值: 源模型的选择。
-
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
- 作用: 将代理模型索引转换为源模型索引。直接返回
proxyIndex
。 - 参数:
proxyIndex
代理模型索引。 - 返回值: 对应的源模型索引。
- 作用: 将代理模型索引转换为源模型索引。直接返回
-
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchStartsWith | Qt::MatchWrap) const override
- 作用: 查找匹配项,默认调用源模型的
match()
。 - 参数:
start
: 起始索引。role
: 数据角色。value
: 匹配值。hits
: 最大匹配数。flags
: 匹配模式。
- 返回值: 匹配的索引列表。
- 作用: 查找匹配项,默认调用源模型的
-
bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override
- 作用: 移动列,默认转发到源模型。
- 参数:
sourceParent
: 源列的父索引。sourceColumn
: 源列起始位置。count
: 移动列数。destinationParent
: 目标父索引。destinationChild
: 目标位置。
- 返回值: 是否成功。
-
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override
- 作用: 移动行,类似
moveColumns
。
- 作用: 移动行,类似
-
QModelIndex parent(const QModelIndex &child) const override
- 作用: 返回子索引的父索引,默认调用源模型的
parent()
。 - 参数:
child
子索引。 - 返回值: 父索引。
- 作用: 返回子索引的父索引,默认调用源模型的
-
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
- 作用: 删除列,默认转发到源模型。
- 参数: 类似
insertColumns
。
-
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
- 作用: 删除行,类似
removeColumns
。
- 作用: 删除行,类似
-
int rowCount(const QModelIndex &parent = QModelIndex()) const override
- 作用: 返回行数,默认调用源模型的
rowCount()
。 - 参数:
parent
父索引。 - 返回值: 行数。
- 作用: 返回行数,默认调用源模型的
-
void setSourceModel(QAbstractItemModel *newSourceModel) override
- 作用: 设置新的源模型,并自动连接信号与槽。
- 参数:
newSourceModel
新的源模型指针。
-
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
- 作用: 返回同一父节点下的兄弟索引,默认调用源模型的
sibling()
。 - 参数:
row
,column
: 目标行号和列号。idx
: 原始索引。
- 返回值: 兄弟索引。
- 作用: 返回同一父节点下的兄弟索引,默认调用源模型的
使用场景总结
- 默认行为:
QIdentityProxyModel
直接透传源模型的结构和操作,常用于在不修改源模型的情况下添加额外逻辑(如数据显示格式、拖放支持)。 - Qt 6.8+ 控制标志:通过
setHandleSourceDataChanges()
和setHandleSourceLayoutChanges()
可优化性能(如关闭自动更新)。 - 重写函数:子类可重写
data()
、setData()
等方法实现自定义逻辑,而无需处理结构映射。