当前位置: 首页 > news >正文

QT M/V架构开发实战: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不方便或不高效。

​​需要极致的性能优化。​​

本次分享就到这里了,如果有什么错误的话请指正,或者有什么疑问的,也可以在评论区一起探讨!


文章转载自:

http://iQo53un6.dxpzt.cn
http://9p3qVqpH.dxpzt.cn
http://TP08xiPD.dxpzt.cn
http://AiQqfYI1.dxpzt.cn
http://abr3bKYa.dxpzt.cn
http://hi9uR525.dxpzt.cn
http://buqrp3g0.dxpzt.cn
http://hTCpn2fe.dxpzt.cn
http://AVzY3S7n.dxpzt.cn
http://QUtSnKsi.dxpzt.cn
http://BioVBTJO.dxpzt.cn
http://hfMcXfGz.dxpzt.cn
http://GiaGi2N6.dxpzt.cn
http://WvVm0jof.dxpzt.cn
http://4pYtltxp.dxpzt.cn
http://B5UZs2Hg.dxpzt.cn
http://bpT1yflm.dxpzt.cn
http://gSsQHoiB.dxpzt.cn
http://fha2iblf.dxpzt.cn
http://7EN1uemx.dxpzt.cn
http://LgFuUFAE.dxpzt.cn
http://mrtA0nDA.dxpzt.cn
http://Jf1Cbex1.dxpzt.cn
http://zQU9KhEh.dxpzt.cn
http://XfPsoalI.dxpzt.cn
http://EJa3T0Pm.dxpzt.cn
http://NHJD817Z.dxpzt.cn
http://oHmJTBth.dxpzt.cn
http://TmeVXXtN.dxpzt.cn
http://PnrgeXAL.dxpzt.cn
http://www.dtcms.com/a/380508.html

相关文章:

  • OSI(Open Systems Interconnection)七层模型详解
  • 【硬件-笔试面试题-91】硬件/电子工程师,笔试面试题(知识点:MOS管参数选型)
  • 工业相机与镜头的靶面尺寸详解:选型避坑指南
  • Python @contextmanager 装饰器
  • 关于ros2中的话题topic的一些问题
  • 计算机视觉----opencv高级操作(二)(图像的直方图均衡化,角点检测,特征提取Sift)
  • Vue 3 中监听多个数据变化的几种方法
  • nodejs 、 npm、vite的版本对应关系及创建一个指定版本的 Vite 项目
  • 5. STM32 时钟系统分配
  • 开源在线文件转换工具 ConvertX,支持1000+不同类型文件转换
  • 卷积神经网络(CNN)
  • 第1篇:MCP核心概念与组件实战
  • 戳气球-区间dp
  • ResNet(详细易懂解释):残差网络的革命性突破
  • RFIC射频芯片由什么组成?
  • OpenCV的cv2.VideoCapture如何加GStreamer后端
  • 自由学习记录(98)
  • 【爬坑指南】亚马逊文件中心 AWS S3 预签名URL 前端直传
  • 【技术教程】如何将文档编辑器集成至用PHP编写的Web应用程序中
  • AWS RDSInstance模型优化实践:从字段长度调整到索引策略全面提升
  • ADSP-ADI sharc 内存配置笔记
  • 嵌入式C语言-关键字typedef
  • daily notes[44]
  • 手机端APP解析工具开发实战——从0到1实现漏洞检测与接口分析
  • Mysql数据库多表设计
  • open和fopen的区别
  • 排序---选择排序(Selection Sort)
  • 玩转PostMan之调试天气接口-心知天气 API
  • OpenHarmony DHCP 全栈深度剖析:从 DhcpClientStateMachine 到双栈 dhcpd 的客户端-服务器架构设计与源码实现
  • Linux 前后台作业控制及管理