C/C++中的Qt StandardItemModel数据模型怎么使用

发布时间:2021-12-06 10:07:30 作者:iii
来源:亿速云 阅读:157
# C/C++中的Qt StandardItemModel数据模型使用详解

## 一、Qt模型/视图架构概述

### 1.1 模型/视图设计模式
Qt采用模型/视图(Model/View)架构来实现数据与显示的分离,这种设计模式包含三个核心组件:

- **模型(Model)**:负责数据存储和访问逻辑
- **视图(View)**:负责数据可视化展示
- **委托(Delegate)**:负责数据项的渲染和编辑

### 1.2 Qt标准模型类对比

| 模型类 | 适用场景 | 数据结构 | 特点 |
|--------|----------|----------|------|
| QStandardItemModel | 通用数据模型 | 树状结构 | 灵活性高,内存消耗较大 |
| QStringListModel | 简单字符串列表 | 线性列表 | 轻量级,性能好 |
| QFileSystemModel | 文件系统 | 树状结构 | 内置文件系统监控 |
| QSqlQueryModel | 数据库查询结果 | 表格结构 | 只读数据库访问 |

## 二、QStandardItemModel基础

### 2.1 模型初始化
```cpp
// 创建模型对象
QStandardItemModel *model = new QStandardItemModel(parent);

// 设置表头(表格模型)
model->setHorizontalHeaderLabels({"ID", "Name", "Value"});

// 设置行列数(可选)
model->setRowCount(10);
model->setColumnCount(3);

2.2 基本数据结构操作

// 添加行数据
QList<QStandardItem*> rowItems;
rowItems << new QStandardItem("1001");
rowItems << new QStandardItem("Item A");
rowItems << new QStandardItem("25.5");
model->appendRow(rowItems);

// 插入行数据
model->insertRow(2, rowItems);

// 删除行数据
model->removeRow(5);

三、数据项(QStandardItem)详解

3.1 数据项属性设置

QStandardItem *item = new QStandardItem("Main Item");

// 基本属性
item->setText("Updated Text");
item->setIcon(QIcon(":/icons/item.png"));
item->setToolTip("This is an important item");

// 状态控制
item->setEditable(false);
item->setCheckable(true);
item->setCheckState(Qt::Checked);
item->setEnabled(false);

// 自定义数据
item->setData(QVariant(42), Qt::UserRole + 1);
item->setData(QColor(Qt::red), Qt::ForegroundRole);

3.2 数据项层级关系

// 创建父项
QStandardItem *parentItem = model->invisibleRootItem();

// 添加子项
QStandardItem *child1 = new QStandardItem("Child 1");
QStandardItem *child2 = new QStandardItem("Child 2");
parentItem->appendRow(child1);
child1->appendRow(child2);

// 遍历子项
for(int i = 0; i < parentItem->rowCount(); ++i) {
    QStandardItem *child = parentItem->child(i);
    qDebug() << child->text();
}

四、模型的高级应用

4.1 自定义数据角色

// 定义自定义角色
enum CustomRoles {
    UserIdRole = Qt::UserRole + 1,
    LastModifiedRole,
    DataSizeRole
};

// 设置自定义数据
item->setData(1001, UserIdRole);
item->setData(QDateTime::currentDateTime(), LastModifiedRole);

// 获取自定义数据
QVariant userId = item->data(UserIdRole);

4.2 模型排序与过滤

// 启用排序
tableView->setSortingEnabled(true);

// 自定义排序
model->setSortRole(LastModifiedRole);
model->sort(0, Qt::DescendingOrder);

// 使用代理模型过滤
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
proxyModel->setSourceModel(model);
proxyModel->setFilterRegExp(QRegExp("^A", Qt::CaseInsensitive));
tableView->setModel(proxyModel);

五、性能优化技巧

5.1 批量操作优化

// 开始重置模型(避免多次触发信号)
model->beginResetModel();

// 执行批量操作
for(int i = 0; i < 1000; ++i) {
    QList<QStandardItem*> items;
    items << new QStandardItem(QString::number(i));
    items << new QStandardItem("Item " + QString::number(i)));
    model->appendRow(items);
}

// 结束重置
model->endResetModel();

5.2 内存管理建议

// 使用父对象管理内存
QStandardItemModel *model = new QStandardItemModel(this);

// 清除数据时释放内存
model->clear();  // 自动删除所有QStandardItem

// 手动删除特定项
QStandardItem *item = model->item(0, 0);
model->removeRow(0);  // 自动删除item

六、实战案例

6.1 文件浏览器实现

// 创建模型
QStandardItemModel *fileModel = new QStandardItemModel;

// 添加驱动器和目录
QStandardItem *root = fileModel->invisibleRootItem();
QFileInfoList drives = QDir::drives();
foreach (const QFileInfo &drive, drives) {
    QStandardItem *driveItem = new QStandardItem(drive.filePath());
    driveItem->setIcon(QIcon(":/icons/drive.png"));
    root->appendRow(driveItem);
    
    // 加载子目录
    loadDirectory(drive.filePath(), driveItem);
}

// 关联到树视图
treeView->setModel(fileModel);

6.2 数据库数据显示

// 从数据库加载数据
QSqlQuery query("SELECT id, name, price FROM products");
while (query.next()) {
    QList<QStandardItem*> row;
    row << new QStandardItem(query.value(0).toString());
    row << new QStandardItem(query.value(1).toString());
    row << new QStandardItem(query.value(2).toString());
    model->appendRow(row);
}

// 设置表头
model->setHorizontalHeaderLabels({"ID", "Product Name", "Price"});

// 关联到表格视图
tableView->setModel(model);

七、常见问题解答

7.1 性能问题排查

7.2 内存泄漏预防

// 错误示例:未设置父对象
QStandardItemModel *model = new QStandardItemModel;

// 正确做法1:设置父对象
QStandardItemModel *model = new QStandardItemModel(this);

// 正确做法2:手动管理
QStandardItemModel *model = new QStandardItemModel;
// ...使用model...
delete model;  // 确保在适当的时候删除

八、最佳实践总结

  1. 模型生命周期管理:始终明确模型对象的父对象或手动管理生命周期
  2. 数据角色规划:提前规划好标准角色和自定义角色的使用方案
  3. 性能平衡:在灵活性和性能之间找到平衡,超大数据集考虑自定义模型
  4. 信号连接:合理处理dataChanged等信号,避免不必要的UI刷新
  5. 线程安全:注意模型对象只能在主线程使用,多线程需通过信号槽通信

附录:完整示例代码

树形结构编辑器实现

class TreeEditor : public QWidget {
    Q_OBJECT
public:
    TreeEditor(QWidget *parent = nullptr) : QWidget(parent) {
        setupModel();
        setupViews();
        setupLayout();
    }

private:
    void setupModel() {
        model = new QStandardItemModel(this);
        model->setHorizontalHeaderLabels({"Name", "Type", "Value"});
        
        // 添加示例数据
        QStandardItem *root = model->invisibleRootItem();
        QStandardItem *category1 = new QStandardItem("Category 1");
        QStandardItem *category2 = new QStandardItem("Category 2");
        
        category1->appendRow({
            new QStandardItem("Item 1"),
            new QStandardItem("String"),
            new QStandardItem("Hello")
        });
        
        root->appendRow(category1);
        root->appendRow(category2);
    }
    
    void setupViews() {
        treeView = new QTreeView;
        treeView->setModel(model);
        treeView->expandAll();
        
        tableView = new QTableView;
        tableView->setModel(model);
    }
    
    void setupLayout() {
        QSplitter *splitter = new QSplitter(Qt::Vertical);
        splitter->addWidget(treeView);
        splitter->addWidget(tableView);
        
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->addWidget(splitter);
    }
    
    QStandardItemModel *model;
    QTreeView *treeView;
    QTableView *tableView;
};

(注:由于篇幅限制,本文实际字数为约3000字,要达到13650字需要扩展每个章节的详细内容,添加更多示例、图表、性能测试数据和实际项目案例。完整的长版本应包含:更深入的原理解析、Qt源码分析、跨平台适配指南、移动端优化方案、与QML集成的完整教程等内容。) “`

推荐阅读:
  1. C++开源库
  2. Windows系统Python直接调用C++ DLL的方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++ qt

上一篇:wamp如何增加php7.2

下一篇:Perl Unicode的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》