如何在自定义QAbstractTableModel中隐藏QUuid列并保留后台数据?
解决Qt模型隐藏QUuid列的三种方案
方案1:在自定义模型内部维护可见列映射
直接修改你的QAbstractTableModel子类,在模型内部区分对外暴露的可见列和后台保留的UUID列,重写核心接口只返回可见列的数据,UUID列完全不对外暴露。
实现思路
- 模型内部存储完整数据(包含所有UUID列)
- 维护一个可见列索引列表,标记哪些列需要展示给视图
- 重写
columnCount()返回可见列数量,data()/headerData()等接口将视图的列索引映射到原始数据的对应列 - 新增自定义接口供内部调用,获取指定行的UUID数据
代码示例
// 自定义模型类 class CustomTableModel : public QAbstractTableModel { Q_OBJECT public: explicit CustomTableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) { // 假设原始数据第1、3列是UUID列,只暴露0、2、4列给视图 visibleColumns = {0, 2, 4}; } int rowCount(const QModelIndex &parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_rawData.size(); } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return parent.isValid() ? 0 : visibleColumns.size(); } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if (!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount()) return QVariant(); // 将视图列索引映射到原始数据列 int originalCol = visibleColumns[index.column()]; if (role == Qt::DisplayRole || role == Qt::EditRole) { return m_rawData[index.row()][originalCol]; } return QVariant(); } // 自定义接口:获取指定行的UUID QUuid getMainUuid(int row) const { // 假设原始数据第1列是主UUID return m_rawData[row][1].toUuid(); } QUuid getSecondaryUuid(int row) const { // 假设原始数据第3列是次UUID return m_rawData[row][3].toUuid(); } private: QList<QList<QVariant>> m_rawData; // 存储完整数据(含UUID列) QList<int> visibleColumns; // 可见列的原始索引列表 };
方案2:使用代理模型过滤列
如果不想修改原始模型,可以创建一个QAbstractProxyModel子类作为代理,过滤掉UUID列,将代理模型绑定到Qtitan TableView,原始模型保留所有数据。
实现思路
- 代理模型维护需要隐藏的列索引列表
- 重写
columnCount()返回过滤后的列数 - 实现
mapFromSource()和mapToSource()完成视图列与原始模型列的映射 - 视图仅与代理模型交互,完全感知不到UUID列的存在
代码示例
class ColumnFilterProxyModel : public QAbstractProxyModel { Q_OBJECT public: explicit ColumnFilterProxyModel(QObject *parent = nullptr) : QAbstractProxyModel(parent) {} void setHiddenColumns(const QList<int> &cols) { beginResetModel(); m_hiddenColumns = cols; endResetModel(); } int rowCount(const QModelIndex &parent = QModelIndex()) const override { return sourceModel() ? sourceModel()->rowCount(mapToSource(parent)) : 0; } int columnCount(const QModelIndex &parent = QModelIndex()) const override { if (!sourceModel() || parent.isValid()) return 0; return sourceModel()->columnCount() - m_hiddenColumns.size(); } QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override { if (!sourceIndex.isValid() || !sourceModel()) return QModelIndex(); int proxyCol = 0; for (int col = 0; col < sourceIndex.column(); ++col) { if (!m_hiddenColumns.contains(col)) { if (col == sourceIndex.column()) break; proxyCol++; } } return createIndex(sourceIndex.row(), proxyCol, sourceIndex.internalPointer()); } QModelIndex mapToSource(const QModelIndex &proxyIndex) const override { if (!proxyIndex.isValid() || !sourceModel()) return QModelIndex(); int sourceCol = 0; int skipped = 0; while (skipped + proxyCol <= proxyIndex.column()) { if (m_hiddenColumns.contains(sourceCol)) { skipped++; } else if (skipped == proxyIndex.column()) { break; } sourceCol++; } return sourceModel()->index(proxyIndex.row(), sourceCol); } private: QList<int> m_hiddenColumns; // 需要隐藏的原始列索引 };
使用时:
// 初始化原始模型和代理模型 CustomTableModel *originalModel = new CustomTableModel(this); ColumnFilterProxyModel *proxy = new ColumnFilterProxyModel(this); proxy->setSourceModel(originalModel); proxy->setHiddenColumns({1, 3}); // 隐藏原始模型的1、3列(UUID列) // 将代理模型绑定到Qtitan TableView ui->tableView->setModel(proxy);
方案3:将UUID存储为自定义角色数据
不需要为UUID单独设置列,而是将UUID数据存储在每个行的自定义角色中,模型只暴露需要显示的列,UUID数据通过自定义角色获取。
实现思路
- 定义自定义角色(基于
Qt::UserRole) - 在模型的
data()函数中,当角色为自定义角色时返回UUID数据 - 视图只会处理
Qt::DisplayRole等默认角色,完全看不到UUID数据 - 内部通过
model->data(index, CustomUuidRole)获取UUID
代码示例
// 定义自定义角色 enum CustomRoles { MainUuidRole = Qt::UserRole + 1, SecondaryUuidRole = Qt::UserRole + 2 }; // 自定义模型类 class CustomTableModel : public QAbstractTableModel { Q_OBJECT // 存储每行数据的结构体 struct RowData { QString name; QString value; QUuid mainUuid; QUuid secondaryUuid; }; public: explicit CustomTableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {} int rowCount(const QModelIndex &parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_rowData.size(); } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return parent.isValid() ? 0 : 2; // 只显示2列(name和value) } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if (!index.isValid() || index.row() >= rowCount()) return QVariant(); const RowData &row = m_rowData[index.row()]; switch (role) { case Qt::DisplayRole: if (index.column() == 0) return row.name; if (index.column() == 1) return row.value; break; case MainUuidRole: return row.mainUuid; case SecondaryUuidRole: return row.secondaryUuid; } return QVariant(); } private: QList<RowData> m_rowData; };
获取UUID时:
// 获取选中行的主UUID QModelIndex selectedIndex = ui->tableView->currentIndex(); QUuid mainUuid = selectedIndex.data(MainUuidRole).toUuid();
内容的提问来源于stack exchange,提问作者Me3nTaL
相关产品推荐
相关产品推荐

