QTransposeProxyModel的函数介绍

前言

Qt版本:6.8.0

作用

QTransposeProxyModel 是 Qt 框架中用于行列转置的代理模型类,其核心作用是将源模型的行列结构进行互换,从而在不修改源模型的前提下,为视图提供转置后的数据展示方式。

1. 行列转置与结构映射

  • 核心功能:将源模型的行变为列,列变为行。例如,源模型中索引 index(2, 3) 的数据,在代理模型中会映射为 index(3, 2)
  • 树形结构支持:若源模型是层级结构(如树形),父节点的索引也会被转置。例如,源模型的父索引 index(2, 0) 在代理中变为 index(0, 2)
  • 自动同步:源模型的数据或布局变更(如插入行、修改值)会通过代理模型自动同步到视图。

2. 视图适配与数据展示

  • 多视图灵活展示:通过转置,同一数据可以在不同视图中以不同形式呈现。例如:
    • 原始视图按行显示时间序列数据。
    • 转置视图按列横向对比不同时间点的数据。
  • 表头转置:源模型的横向表头(如列标题)在代理模型中变为纵向表头,反之亦然[ citation:1]。

3. 与视图交互的适配

  • 操作转发:代理模型会将对视图的操作(如插入行、删除列)转换为对源模型的对应操作。例如:
    • 在代理模型中调用 insertRows(0, 2) 实际会向源模型插入两列。
  • 选择模型同步:若多个视图共享同一源模型(一个原始视图,一个转置视图),需处理选择模型的同步。例如,需将原始视图的行选择转换为转置视图的列选择,需通过 QItemSelection 的映射函数实现。

4. 典型应用场景

  1. 数据横向对比
    将纵向排列的数据转为横向,方便比较不同维度的数值。例如,将“月份”从行标签转为列标签,显示各月份的指标对比。

  2. 适配不同显示需求
    当视图空间有限时,转置可优化布局。例如,移动端应用中,横向滚动显示原本纵向排列的数据。

  3. 树形数据转置
    层级数据的行列互换。例如,将父子关系的树形结构转置为以列表示层级。

  4. 动态数据展示
    结合其他代理模型(如 QSortFilterProxyModel),实现动态排序或过滤后的转置显示。


与其他代理模型的对比

代理模型核心功能适用场景
QTransposeProxyModel行列互换数据横向对比、视图适配
QIdentityProxyModel保持结构不变,扩展数据或拦截操作数据格式化、权限控制
QSortFilterProxyModel动态排序和过滤搜索过滤、条件筛选

使用示例

// 创建源模型和转置代理
QAbstractItemModel *sourceModel = new MyTableModel();
QTransposeProxyModel *proxyModel = new QTransposeProxyModel();
proxyModel->setSourceModel(sourceModel);

// 设置视图
QTableView originalView, transposedView;
originalView.setModel(sourceModel);
transposedView.setModel(proxyModel);

// 转置后,原模型的行变为代理模型的列,反之亦然

注意事项

  • 索引转换复杂性:若需在转置视图中实现复杂交互(如跨视图拖放),需手动处理索引映射(通过 mapToSourcemapFromSource)。
  • 性能考量:转置可能增加数据访问的复杂度,需避免在大型数据集上频繁操作。

QTransposeProxyModel 通过简单的行列互换,为数据展示提供了更多灵活性,适用于需要多角度分析或适配不同界面布局的场景。其核心优势在于非侵入式地扩展源模型的显示方式,同时保持数据源的独立性。

函数

QTransposeProxyModel(QObject *parent = nullptr)

构造函数,用于创建一个转置代理模型对象。

  • 参数parent(QObject*,可选),父对象指针,通常用于Qt对象树管理。
  • 返回值:无。

~QTransposeProxyModel()

析构函数,销毁转置代理模型对象,释放资源。

  • 参数:无。
  • 返回值:无。

主要重写的公有函数

int columnCount(const QModelIndex &parent = QModelIndex()) const override

返回指定父项下的列数。对于转置模型,通常返回源模型的行数。

  • 参数parent(QModelIndex),父项索引,默认是无效索引(即顶层)。
  • 返回值:int,列数。
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override

返回表头数据。对于转置模型,行列头会互换。

  • 参数
    • section(int):表头的节号(行号或列号)。
    • orientation(Qt::Orientation):方向(Qt::Horizontal 水平或 Qt::Vertical 垂直)。
    • role(int):角色,通常为 Qt::DisplayRole
  • 返回值:QVariant,表头显示的数据。
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override

返回指定行列和父项的模型索引。

  • 参数
    • row(int):行号。
    • column(int):列号。
    • parent(QModelIndex):父项索引,默认无效。
  • 返回值:QModelIndex,指定位置的索引。
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override

在指定位置插入列。

  • 参数
    • column(int):插入起始列号。
    • count(int):插入的列数。
    • parent(QModelIndex):父项索引。
  • 返回值:bool,插入是否成功。
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override

在指定位置插入行。

  • 参数
    • row(int):插入起始行号。
    • count(int):插入的行数。
    • parent(QModelIndex):父项索引。
  • 返回值:bool,插入是否成功。
QMap<int, QVariant> itemData(const QModelIndex &index) const override

返回指定索引的所有角色数据。

  • 参数index(QModelIndex),目标索引。
  • 返回值:QMap<int, QVariant>,键为角色,值为数据。
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override

将源模型的索引映射到代理模型的索引(转置后的位置)。

  • 参数sourceIndex(QModelIndex),源模型索引。
  • 返回值:QModelIndex,代理模型中的索引。
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override

将代理模型的索引映射回源模型的索引。

  • 参数proxyIndex(QModelIndex),代理模型索引。
  • 返回值:QModelIndex,源模型中的索引。
bool moveColumns(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override

移动列。

  • 参数
    • sourceParent(QModelIndex):源父项。
    • sourceRow(int):源起始行。
    • count(int):移动的列数。
    • destinationParent(QModelIndex):目标父项。
    • destinationChild(int):目标子项位置。
  • 返回值:bool,移动是否成功。
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override

移动行。

  • 参数:同上,只是针对行。
  • 返回值:bool,移动是否成功。
QModelIndex parent(const QModelIndex &index) const override

返回指定索引的父项索引。

  • 参数index(QModelIndex),目标索引。
  • 返回值:QModelIndex,父项索引。
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override

移除指定位置的列。

  • 参数
    • column(int):起始列号。
    • count(int):移除的列数。
    • parent(QModelIndex):父项索引。
  • 返回值:bool,移除是否成功。
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override

移除指定位置的行。

  • 参数
    • row(int):起始行号。
    • count(int):移除的行数。
    • parent(QModelIndex):父项索引。
  • 返回值:bool,移除是否成功。
int rowCount(const QModelIndex &parent = QModelIndex()) const override

返回指定父项下的行数。对于转置模型,通常返回源模型的列数。

  • 参数parent(QModelIndex),父项索引。
  • 返回值:int,行数。
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override

设置表头数据。

  • 参数
    • section(int):节号。
    • orientation(Qt::Orientation):方向。
    • value(QVariant):要设置的数据。
    • role(int):角色,通常为 Qt::EditRole
  • 返回值:bool,设置是否成功。
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override

设置指定索引的多个角色数据。

  • 参数
    • index(QModelIndex):目标索引。
    • roles(QMap<int, QVariant>):角色与数据的映射。
  • 返回值:bool,设置是否成功。
void setSourceModel(QAbstractItemModel *newSourceModel) override

设置源数据模型。

  • 参数newSourceModel(QAbstractItemModel*),新的源模型指针。
  • 返回值:无。
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override

对指定列进行排序。

  • 参数
    • column(int):要排序的列号。
    • order(Qt::SortOrder):排序顺序(升序或降序)。
  • 返回值:无。
QSize span(const QModelIndex &index) const override

返回指定索引的单元格跨越的行和列数(用于合并单元格)。

  • 参数index(QModelIndex),目标索引。
  • 返回值:QSize,宽为跨越的列数,高为跨越的行数。

示例

1. columnCount

QTransposeProxyModel proxy;
proxy.setSourceModel(sourceModel);
int cols = proxy.columnCount(); // 获取转置后表格的列数

2. headerData

QString header = proxy.headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(); // 获取第0列的表头

3. index

QModelIndex idx = proxy.index(1, 2); // 获取转置后第1行第2列的索引

4. insertColumns

bool ok = proxy.insertColumns(1, 2); // 在转置后第1列插入2列

5. insertRows

bool ok = proxy.insertRows(0, 1); // 在转置后第0行插入1行

6. itemData

QModelIndex idx = proxy.index(0, 0);
QMap<int, QVariant> roles = proxy.itemData(idx); // 获取索引的所有角色数据

7. mapFromSource

QModelIndex srcIdx = sourceModel->index(2, 3);
QModelIndex proxyIdx = proxy.mapFromSource(srcIdx); // 源模型索引转为代理模型索引

8. mapToSource

QModelIndex proxyIdx = proxy.index(1, 2);
QModelIndex srcIdx = proxy.mapToSource(proxyIdx); // 代理模型索引转为源模型索引

9. moveColumns

proxy.moveColumns(QModelIndex(), 0, 1, QModelIndex(), 2); // 移动第0列到第2列

10. moveRows

proxy.moveRows(QModelIndex(), 1, 1, QModelIndex(), 3); // 移动第1行到第3行

11. parent

QModelIndex idx = proxy.index(0, 0);
QModelIndex parentIdx = proxy.parent(idx); // 获取索引的父项

12. removeColumns

proxy.removeColumns(0, 1); // 移除第0列

13. removeRows

proxy.removeRows(0, 2); // 移除第0行开始的2行

14. rowCount

int rows = proxy.rowCount(); // 获取转置后表格的行数

15. setHeaderData

proxy.setHeaderData(0, Qt::Vertical, "新表头", Qt::EditRole); // 设置第0行的表头

16. setItemData

QModelIndex idx = proxy.index(0, 0);
QMap<int, QVariant> roles;
roles[Qt::DisplayRole] = "新内容";
proxy.setItemData(idx, roles); // 设置索引的显示内容

17. setSourceModel

proxy.setSourceModel(sourceModel); // 设置源模型

18. sort

proxy.sort(1, Qt::DescendingOrder); // 按第1列降序排序

19. span

QModelIndex idx = proxy.index(0, 0);
QSize cellSpan = proxy.span(idx); // 获取单元格的跨行跨列信息

如需更详细的实际应用场景代码,可进一步说明。

如何使用

一般情况下,如果你直接使用 Qt 官方提供的 QTransposeProxyModel,这些函数(如 rowCountcolumnCountmapFromSourcemapToSource 等)已经在 QTransposeProxyModel 内部被正确重写,实现了行列转置的逻辑。你无需再自己重写这些函数,只需要像普通的代理模型一样使用它即可。

你只需要做的事情:
  1. 创建你的源模型(如 QAbstractTableModel 的子类)。
  2. 创建 QTransposeProxyModel 实例,并设置源模型:
    QTransposeProxyModel *transposeModel = new QTransposeProxyModel(this);
    transposeModel->setSourceModel(yourSourceModel);
    
  3. transposeModel 设置给你的视图(如 QTableView):
    tableView->setModel(transposeModel);
    
只有在以下情况下才需要重写
  • 你有特殊的转置逻辑需求(比如只转置部分区域,或有特殊的行列映射规则)。
  • 你需要对某些行为进行自定义(比如自定义 headerData 的显示方式等)。

否则,直接用 Qt 提供的 QTransposeProxyModel 即可,无需自己重写这些函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值