好的,我们来系统、直观地讲解一下 C++ Qt 中的 QStandardItemModel 数据模型组件,包括它的作用、常见用法、优缺点和典型代码示例。


1. QStandardItemModel 是什么

  • 属于 Qt Model/View 架构 中的 通用数据模型类
  • 提供了一个基于 表格(二维)数据 的默认实现,可以很方便地存储、管理、显示数据
  • 可以与 QTableViewQTreeViewQListView 等视图组件配合使用
  • 内部数据以 QStandardItem 为单元格元素存储,每个单元格都可以包含:
    • 文本
    • 图标
    • 对齐方式
    • 自定义数据(QVariant

2. 适用场景

  • 需要在表格、树形、列表中显示和编辑数据,但不想手动继承 QAbstractItemModel 时
  • 快速原型开发
  • 静态数据或中小规模动态数据展示
  • 配合 QTableView 做简单的 CRUD(增删改查)

3. 基本结构

QStandardItemModel 实质上是一个 行 × 列 的二维数据结构,但它的每个 QStandardItem 还可以有自己的子项,从而支持树状数据。

数据访问方法:

  • 行列访问setItem(row, col, item)item(row, col)
  • 标题设置setHorizontalHeaderLabels()setVerticalHeaderLabels()
  • 数据读写setData(index, value)data(index)

4. 基本用法示例

#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QStandardItem>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建模型,3 行 2 列
    QStandardItemModel model(3, 2);

    // 设置表头
    model.setHorizontalHeaderLabels({"姓名", "年龄"});

    // 填充数据
    model.setItem(0, 0, new QStandardItem("张三"));
    model.setItem(0, 1, new QStandardItem("25"));

    model.setItem(1, 0, new QStandardItem("李四"));
    model.setItem(1, 1, new QStandardItem("30"));

    model.setItem(2, 0, new QStandardItem("王五"));
    model.setItem(2, 1, new QStandardItem("28"));

    // 创建视图并绑定模型
    QTableView view;
    view.setModel(&model);
    view.show();

    return app.exec();
}

5. 常用操作

5.1 设置单元格数据

QStandardItem *item = new QStandardItem("Hello");
item->setTextAlignment(Qt::AlignCenter);
item->setIcon(QIcon(":/icons/user.png"));
item->setData(123, Qt::UserRole);  // 存储额外数据
model.setItem(0, 0, item);

5.2 获取单元格数据

QStandardItem *item = model.item(0, 0);
QString text = item->text();
int myData = item->data(Qt::UserRole).toInt();

5.3 添加行

QList<QStandardItem*> rowItems;
rowItems << new QStandardItem("赵六") << new QStandardItem("22");
model.appendRow(rowItems);

5.4 删除行

model.removeRow(1);  // 删除第 2 行

6. 优缺点对比

优点缺点
简单易用,不需继承复杂的 QAbstractItemModel大量数据时性能一般
支持树形、表格、列表统一接口占用内存较多
直接支持编辑、排序、拖拽灵活度不如自定义模型
每个单元格可附加任意数据不适合非常大规模动态数据

7. 进阶技巧

7.1 与 QTreeView 结合

QStandardItemModel treeModel;
QStandardItem *root = treeModel.invisibleRootItem();
QStandardItem *parentItem = new QStandardItem("父节点");
parentItem->appendRow(new QStandardItem("子节点1"));
parentItem->appendRow(new QStandardItem("子节点2"));
root->appendRow(parentItem);

7.2 响应数据变化

QObject::connect(&model, &QStandardItemModel::itemChanged, [](QStandardItem *item){
    qDebug() << "Cell changed:" << item->text();
});