You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 01:15:36