QT M/V架构开发实战:QStandardItemModel介绍
目录
- @[TOC](目录)
- 前言
- 一、QStandardItemModel初步介绍
- 二、基本功能
- 1.创建
- 2.基本属性与方法
- 三、何时使用 QStandardItemModel?
- 四、何时避免使用 QStandardItemModel?
目录
- @[TOC](目录)
- 前言
- 一、QStandardItemModel初步介绍
- 二、基本功能
- 1.创建
- 2.基本属性与方法
- 三、何时使用 QStandardItemModel?
- 四、何时避免使用 QStandardItemModel?
前言
本文主要介绍的是使用代码生成的情况下对控件的介绍,包括拥有的功能及能修改的样式,也会说明在qtdesiner拖拽控件生成和使用代码生成控件的区别(如果有的话,遇到了的会说),此版本不属于最终版本,以后遇到什么新奇的点会继续更新!本文基于QT官方的文档进行的编写,QT版本为qt 5.14.0,编写环境为Windows11。不得不说官方文档真是个好东西,有时候有些不会的上去一看就能有灵感解决了,可惜没有中文版本的。
一、QStandardItemModel初步介绍
QStandardItemModel是 QAbstractItemModel的一个具体实现。它的核心思想是使用 QStandardItem对象来存储和管理数据。每个 QStandardItem代表模型中的一个数据项(单元格),它可以存储数据(通过角色)、设置标志(可编辑、可选等)、拥有子项(构建树结构)等。
核心优势:
1.简单易用: 相比直接继承 QAbstractItemModel并实现所有纯虚函数,使用 QStandardItemModel要简单得多。你只需要创建 QStandardItem对象并填充到模型中即可。
2.内置功能: 它自动处理了数据变化通知(dataChanged信号)、结构变化通知(行/列插入删除的信号)等繁琐工作。你修改 QStandardItem的属性,模型会自动发出相应信号通知视图更新。
3.灵活性: 非常适合表示表格数据(二维)和树状数据(层次结构)。
4.集成 QStandardItem: QStandardItem本身功能强大,可以存储多种类型的数据(文本、图标、颜色、字体等),设置各种属性(对齐、背景、前景、勾选状态等)。
二、基本功能
1.创建
// 创建一个空模型,可以稍后设置行列
QStandardItemModel *model = new QStandardItemModel(parent);
// 创建时指定初始行数和列数
QStandardItemModel *model = new QStandardItemModel(rows, columns, parent);
2.基本属性与方法
1)设置表头
// 设置水平表头标签 (列名)
model->setHorizontalHeaderLabels(QStringList() << "Name" << "Age" << "Department");
// 设置垂直表头标签 (行名,较少用)
model->setVerticalHeaderLabels(QStringList() << "Row 1" << "Row 2");
// 获取水平表头项 (QStandardItem*),可以进一步设置其属性(字体、颜色等)
QStandardItem *headerItem = model->horizontalHeaderItem(column);
headerItem->setTextAlignment(Qt::AlignCenter);
headerItem->setBackground(QBrush(Qt::lightGray));
2)创建数据项()
// 创建一个包含文本的项
QStandardItem *itemName = new QStandardItem("Alice");
// 创建一个包含文本和图标的项
QStandardItem *itemWithIcon = new QStandardItem(QIcon(":/images/user.png"), "Bob");
// 创建一个可勾选的项
QStandardItem *checkableItem = new QStandardItem("Task Complete");
checkableItem->setCheckable(true);
checkableItem->setCheckState(Qt::Checked); // 或 Qt::Unchecked
3)设置项到模型
// 设置单个项到指定位置 (行, 列)
model->setItem(row, column, item);
// 设置整行数据 (一个 QStandardItem 列表代表一行中的各列)
QList<QStandardItem*> rowItems;
rowItems << new QStandardItem("Alice") << new QStandardItem("28") << new QStandardItem("Engineering");
model->appendRow(rowItems); // 添加到末尾
model->insertRow(row, rowItems); // 插入到指定行
// 设置整列数据 (较少用)
QList<QStandardItem*> columnItems;
// ... 填充列数据 ...
model->appendColumn(columnItems);
model->insertColumn(column, columnItems);
4)获取项
// 获取指定位置的项 (行, 列)
QStandardItem *item = model->item(row, column);
// 获取水平表头项 (列)
QStandardItem *headerItem = model->horizontalHeaderItem(column);
// 获取垂直表头项 (行)
QStandardItem *vHeaderItem = model->verticalHeaderItem(row);
5)操作行和列
// 插入行
model->insertRow(row); // 插入空行
model->insertRow(row, listOfItems); // 插入带数据的行// 插入列
model->insertColumn(column); // 插入空列
model->insertColumn(column, listOfItems); // 插入带数据的列 (每项代表该列的一行)// 追加行/列
model->appendRow(listOfItems);
model->appendColumn(listOfItems);// 删除行/列
model->removeRow(row);
model->removeRows(row, count); // 删除从 row 开始的 count 行
model->removeColumn(column);
model->removeColumns(column, count); // 删除从 column 开始的 count 列// 获取行/列数
int rows = model->rowCount();
int cols = model->columnCount();
int colsForRow = model->rowCount(parentIndex); // 对于树状结构,获取父节点下的行数
6)构建树状结构 (层次数据)
// 创建父项
QStandardItem *parentItem = model->invisibleRootItem(); // 获取模型的根项 (不可见)
// 或者创建一个顶级项
QStandardItem *topLevelItem = new QStandardItem("Departments");// 创建子项
QStandardItem *childItem1 = new QStandardItem("Engineering");
QStandardItem *childItem2 = new QStandardItem("Marketing");// 将子项添加到父项下 (作为一行)
parentItem->appendRow(childItem1);
parentItem->appendRow(childItem2);
// 或者 topLevelItem->appendRow(childItem1);// 也可以添加一整行子项到父项下
QList<QStandardItem*> childRow;
childRow << new QStandardItem("Alice") << new QStandardItem("Developer");
parentItem->appendRow(childRow); // parentItem 下新增一行,包含两列// 获取父项的子项
QStandardItem *firstChild = parentItem->child(row, column); // 获取指定位置的子项
int childCount = parentItem->rowCount(); // 获取子项行数 (直接子节点数)// 获取项的父项
QStandardItem *parentOfChild = childItem1->parent();
7)访问和修改项数据 (QStandardItem的接口)
// 设置/获取文本 (DisplayRole)
item->setText("New Name");
QString name = item->text();// 设置/获取图标 (DecorationRole)
item->setIcon(QIcon(":/images/icon.png"));
QIcon icon = item->icon();// 设置/获取字体 (FontRole)
QFont boldFont;
boldFont.setBold(true);
item->setFont(boldFont);
QFont usedFont = item->font();// 设置/获取文本对齐 (TextAlignmentRole)
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
Qt::Alignment align = item->textAlignment();// 设置/获取背景色 (BackgroundRole)
item->setBackground(QBrush(Qt::yellow));
QBrush bgBrush = item->background();// 设置/获取前景色 (文本颜色, ForegroundRole)
item->setForeground(QBrush(Qt::red));
QBrush fgBrush = item->foreground();// 设置/获取勾选状态和是否可勾选 (CheckStateRole, ItemIsUserCheckable flag)
item->setCheckable(true);
item->setCheckState(Qt::Checked); // Qt::Unchecked, Qt::PartiallyChecked
bool isChecked = (item->checkState() == Qt::Checked);
bool isCheckable = item->isCheckable();// 设置/获取是否可编辑 (ItemIsEditable flag)
item->setEditable(false);
bool editable = item->isEditable();// 设置/获取是否启用 (ItemIsEnabled flag)
item->setEnabled(false);
bool enabled = item->isEnabled();// 设置/获取是否可选 (ItemIsSelectable flag)
item->setSelectable(false); // 注意:通常通过 flags() 设置,但 QStandardItem 提供了这个便捷方法
bool selectable = item->isSelectable();// 设置/获取工具提示 (ToolTipRole)
item->setToolTip("This is an important item");
QString tip = item->toolTip();// 设置/获取状态提示 (StatusTipRole)
item->setStatusTip("Shows in status bar");
QString statusTip = item->statusTip();// 设置/获取自定义数据 (使用 Qt::UserRole 或更高)
item->setData(QVariant(42), Qt::UserRole); // 存储一个整数
item->setData(QVariant("Custom Info"), Qt::UserRole + 1); // 存储一个字符串
int customInt = item->data(Qt::UserRole).toInt();
QString customStr = item->data(Qt::UserRole + 1).toString();// 获取项的标志 (flags)
Qt::ItemFlags flags = item->flags();
8)查找项
// 通过文本查找项 (精确匹配,遍历所有项)
QList<QStandardItem*> foundItems = model->findItems("Alice", Qt::MatchExactly);// 通过文本查找项 (匹配开头、包含、正则等,Qt::MatchFlag)
QList<QStandardItem*> foundStartsWith = model->findItems("A", Qt::MatchStartsWith);// 查找指定项所在的行和列 (需要知道父项)
QStandardItem *parentItem = ...; // 父项 (或 invisibleRootItem())
int row = item->row();
int column = item->column();
9)排序
// 启用视图排序 (最简单)
tableView->setSortingEnabled(true); // 用户点击表头即可排序// 在代码中排序 (基于列)
model->sort(column, Qt::AscendingOrder); // 升序
model->sort(column, Qt::DescendingOrder); // 降序// 自定义排序规则 (需要继承 QStandardItemModel 并重写 lessThan)
class MySortModel : public QStandardItemModel {
protected:bool lessThan(const QModelIndex &left, const QModelIndex &right) const override {// 获取数据进行比较,left 和 right 是同一列的不同行索引QVariant leftData = data(left);QVariant rightData = data(right);// ... 实现你的比较逻辑 ...return myCustomComparisonResult;}
};
10)与视图连接
QTableView *tableView = new QTableView;
tableView->setModel(model); // 关键一步!QTreeView *treeView = new QTreeView;
treeView->setModel(model); // 如果 model 是树状结构
三、何时使用 QStandardItemModel?
数据量不大: 内存中可以容纳所有 QStandardItem对象。
数据结构相对简单: 表格或树状结构。
需要快速开发: 不想花费精力实现完整的 QAbstractItemModel。
需要灵活设置单元格属性: QStandardItem提供了丰富的属性设置接口。
四、何时避免使用 QStandardItemModel?
数据量巨大 (百万级): 创建和管理大量 QStandardItem对象会消耗大量内存和 CPU,性能会成为瓶颈。此时应使用自定义的 QAbstractItemModel(如基于 QAbstractTableModel),实现按需提供数据的 data()函数。
数据源特殊: 数据来自数据库、网络或其他复杂来源,直接映射到 QStandardItem不方便或不高效。
需要极致的性能优化。
本次分享就到这里了,如果有什么错误的话请指正,或者有什么疑问的,也可以在评论区一起探讨!