目录
QAbstractTableModel是Qt 框架中模型/视图架构的核心类之一,处理表格数据的基石类,专门用于为表格形式的数据(二维表格)提供模型支持。它继承自QAbstractItemModel,是QTableView视图组件的理想搭档。通过重写关键函数实现:
- 定义表格结构(行/列数)
- 提供单元格数据
- 支持编辑和样式定制 它赋予开发者完全控制表格行为的能力,是实现复杂表格视图的首选方案。
核心作用
- 数据抽象层
将原始数据(如数据库、文件、内存结构)抽象为表格结构(行和列),供QTableView等视图组件显示和编辑。 - 解耦数据与UI
遵循 MVC(Model-View-Controller) 设计模式,分离数据逻辑与界面渲染。
必须重写的关键虚函数
| 函数签名 | 作用 | 示例返回值 |
|---|---|---|
| int rowCount(const QModelIndex &parent) const | 返回行数 | myData.size() |
| int columnCount(const QModelIndex &parent) const | 返回列数 | myData[0].size() |
| QVariant data(const QModelIndex &index, int role) const | 返回单元格数据 | return myData[row][col]; |
常用可选重写函数
QVariant headerData(int section, Qt::Orientation orientation, int role) const
设置表头标题(水平/垂直)。
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal)
return QString("Column %1").arg(section);
else
return QString("Row %1").arg(section);
}
bool setData(const QModelIndex &index, const QVariant &value, int role)
编辑数据时调用(需配合flags()启用编辑)。Qt::ItemFlags flags(const QModelIndex &index) const
设置单元格属性(如可编辑、可选中等):
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
关键特性
角色(Role)系统
通过 data() 的 role 参数区分数据类型:
Qt::DisplayRole:显示的文本(如"John")Qt::EditRole:编辑时的原始数据Qt::BackgroundRole:单元格背景色Qt::TextAlignmentRole:文本对齐方式
if (role == Qt::BackgroundRole)
return QBrush(Qt::yellow);
- 索引(QModelIndex)
- 通过
index(row, col)创建单元格索引 - 用
index.row()和index.column()获取位置
- 数据修改通知
修改数据后需手动触发信号:
- 单单元格更新:
emit dataChanged(topLeft, bottomRight) - 增/删行:调用
beginInsertRows()/endInsertRows()
使用流程
1、继承QAbstractTableModel
class MyModel : public QAbstractTableModel {
Q_OBJECT
public:
// 重写虚函数...
};
2、实现数据存取
// 示例:内存数据存储
QVector<QVector<QString>> tableData;
3、链接视图
QTableView *view = new QTableView;
MyModel *model = new MyModel;
view->setModel(model); // 绑定模型与视图
使用场景是?
- 需要显示二维表格数据(如 Excel 样式)
- 数据需要支持动态修改(增删行/列)
- 需要自定义单元格样式(颜色、字体等)
样例代码
// 自定义模型
class CustomTableModel : public QAbstractTableModel {
public:
int rowCount(const QModelIndex&) const override { return 3; }
int columnCount(const QModelIndex&) const override { return 2; }
QVariant data(const QModelIndex &index, int role) const override {
if (role == Qt::DisplayRole)
return QString("Cell %1,%2").arg(index.row()).arg(index.column());
return QVariant();
}
};
// 在视图中使用
QTableView tableView;
CustomTableModel model;
tableView.setModel(&model);
tableView.show(); // 显示3x2表格
对比其他模型类
Qt 提供了超过 10 种模型类支持表格数据展示
在 Qt 的模型/视图架构中,除了您提到的四种模型类(`QAbstractListModel`、`QStandardItemModel`、`QSqlTableModel`、`QAbstractTableModel`),还有**其他重要模型类**可用于表格数据展示。以下是完整的分类总结:
1. 基础抽象模型(必须继承实现)
| 类名 | 用途 | 表格适用性 |
|---|---|---|
| QAbstractItemModel | 所有模型的基类(树/表/列表) | ★★★ |
| QAbstractTableModel | 表格专用基础模型 | ★★★ |
| QAbstractListModel | 单列列表基础模型(如 QListView) | ★ |
2. 便捷模型(可直接使用)
| 类名 | 用途 | 表格适用性 |
|---|---|---|
| QStandardItemModel | 通用内存模型(支持树/表)简单表格(无需自定义模型) | ★★★ |
| QStringListModel | 字符串列表专用模型 | ★ |
3. 数据库模型(直接操作数据库表)
| 类名 | 用途 | 表格适用性 |
|---|---|---|
| QSqlTableModel | 单数据库表模型 | ★★★ |
| QSqlQueryModel | 只读 SQL 查询结果模型 | ★★★ |
| QSqlRelationalTableModel | 支持外键关系的表模型 | ★★★ |
4. 文件系统模型
| 类名 | 用途 | 表格适用性 |
|---|---|---|
| QFileSystemModel | 文件系统浏览器模型 | ★★ (可显示表格) |
| QDirModel | 已废弃的文件系统模型 | ✘ |
5. 代理模型(数据转换层)
| 类名 | 用途 | 表格适用性 |
|---|---|---|
| QSortFilterProxyModel | 排序/过滤代理 | ★★★ |
| QIdentityProxyModel | 透明数据传递代理 | ★★★ |
| QTransposeProxyModel | 行列转置代理 | ★★★ |
| QConcatenateTablesProxyModel | 多表拼接代理 | ★★★ |
完整模型类关系图
QAbstractItemModel
├── QAbstractTableModel // 表格基础
│ ├── QSqlTableModel // 数据库表
│ ├── QSqlRelationalTableModel
│ └── [Your Custom Model]
├── QAbstractListModel // 列表基础
│ └── QStringListModel // 字符串列表
└── QStandardItemModel // 通用内存模型
代理模型(独立层级):
QAbstractProxyModel
├── QSortFilterProxyModel // 排序过滤
├── QIdentityProxyModel // 透明传递
├── QTransposeProxyModel // 行列转置
└── QConcatenateTablesProxyModel // 表合并
关键模型类详解
1. QSqlQueryModel (重要补充)
- 用途:显示任意 SQL 查询结果(
SELECT语句) - 表格适用性:★★★★★
QSqlQueryModel model; model.setQuery("SELECT name, salary FROM employees");
QTableView view; view.setModel(&model); // 直接显示结果集
- 优势:比
QSqlTableModel更灵活,支持复杂查询 - 限制:默认只读(需额外代码实现编辑)
2. 代理模型(表格增强神器)
QSortFilterProxyModel:
// 示例:实现实时过滤 QSortFilterProxyModel proxy; proxy.setSourceModel(sourceModel); // 源模型
proxy.setFilterKeyColumn(0); // 按第一列过滤 proxy.setFilterRegularExpression("John"); view.setModel(&proxy);
QTransposeProxyModel:
// 行列转置(行变列,列变行)
QTransposeProxyModel proxy;
proxy.setSourceModel(sourceModel);
view.setModel(&proxy); // 显示转置后的表格
3. QFileSystemModel (特殊表格)
- 显示文件系统信息(名称/大小/类型/修改日期)
- 表格模式:
QFileSystemModel model;
model.setRootPath("/");
QTableView view;
view.setModel(&model);
view.setRootIndex(model.index("/path"));
何时选择哪种模型?
| 场景 | 推荐模型 |
|---|---|
| 自定义内存表格 | QAbstractTableModel 或 QStandardItemModel |
| 数据库单表编辑 | QSqlTableModel |
| 复杂SQL查询展示 | QSqlQueryModel |
| 字符串列表 | QStringListModel |
| 文件浏览器 | QFileSystemModel |
| 表格排序/过滤 | QSortFilterProxyModel + 任意源模型 |
| 行列转置 | QTransposeProxyModel |
完整代码示例:代理模型组合
// 创建源模型(数据库)
QSqlTableModel sourceModel;
sourceModel.setTable("employees");
sourceModel.select();
// 创建代理链:排序 -> 转置 -> 过滤
QSortFilterProxyModel sortProxy;
sortProxy.setSourceModel(&sourceModel);
sortProxy.sort(0, Qt::AscendingOrder); // 按第0列排序
QTransposeProxyModel transposeProxy;
transposeProxy.setSourceModel(&sortProxy);
QSortFilterProxyModel filterProxy;
filterProxy.setSourceModel(&transposeProxy);
filterProxy.setFilterRegularExpression("Manager");
// 最终视图
QTableView view;
view.setModel(&filterProxy); // 显示:转置+排序+过滤后的表格
总结
Qt 提供了超过 10 种模型类支持表格数据展示,核心包括:
- 基础模型:
QAbstractTableModel,QStandardItemModel - 数据库模型:
QSqlTableModel,QSqlQueryModel,QSqlRelationalTableModel - 代理模型:
QSortFilterProxyModel,QTransposeProxyModel(极大扩展表格能力) - 专用模型:
QFileSystemModel,QStringListModel
通过组合基础模型 + 代理模型,几乎可以实现任何复杂度的表格需求,
这是 Qt 模型/视图架构的强大之处。




