转载:落叶知秋时

类QabstractItemModel,QabstractListModel,QAbstractTableModel不保存数据,用户需要从这些类派生出子类,并在子类中定义某种数据结构来保存数据。

与此不同,类QStandardItemModel负责保存数据,每个数据项被表示为类QStandardItem的对象。接下来,我们主要从两个方面介绍类QStandardItemMode的内容。

  1. 首先阐述如何使用类QStandardItem保存一个数据项,
  2. 再阐述如何使用类QStandardItemModel将这些数据项组织起来,形成列表、表格或者树,以供其他视图类显示。

首先来看第一方面:

如前文所述,一个数据项由若干个『角色,数据子项』对组成。类QStandardItem负责保存、访问这些数据。该类的内部定义了一个类型为QVector的容器,

每个容器元素本质上存放一个『角色,数据子项』对。由于各个角色对应的数据子项可能具有不同的类型,Qt使用QVariant来存放每个数据子项。

当用户希望将一些数据存放在一个QStandardItem对象中时,可以调用其成员函数:

void setData ( const QVariant & value, int role)    //将『role, value』对存入。

当用户希望读取该对象中的数据时,可以调用另外一个成员函数:

QVariant data ( int role = ) const    //读取角色role对应的数据子项。

以上两个函数是QStandardItem的核心。有了这两个函数,我们就可以访问该类所表示数据项的任何一个『角色,数据子项』对。然而,对于一些常用角色,

该类提供了更加简洁、容易记忆的成员函数。例如,当一个数据项被显示在视图中时,它往往包含一些文字、一个图标,还可能包含一个复选框。

常用角色:

  • Qt::BackgroundRole控制显示背景,
  • Qt::FontRole控制文字字体,
  • Qt::ForegroundRole控制文字颜色,
  • Qt::CheckStateRole控制复选框的状态。

该类提供的一组成员函数可以方便地访问这些常用角色对应的数据子项:

  • 成员函数setBackground()、background()分别设置/返回背景刷子。
  • 函数setFont()、font()分别设置/返回文字字体。
  • 函数setForeground()、foreground()分别设置/返回字体颜色。
  • 函数setCheckState()、checkState()分别设置/返回复选框状态。

然后再来看第二方面:

类QStandardItemModel将类QStandardItem表示的数据项组织起来,形成列表、表格、树甚至更复杂的数据结构。

  • 该类提供了一组成员函数,向这些数据结构添加新的数据项,更改已经存在的数据项,或者删除已有的数据项。
  • 另一方面,作为一个模型类,它实现了QAbstractItemModel定义的接口函数,以使其他视图类能够访问模型中的数据项。

1:如果数据集被表示为一个列表,我们可以调用类QStandardItemModel的成员函数appendRow()向列表中添加一个数据项,使用item()读取一个数据项。

如代码段13-10所示。

  • 行①获取模型最顶层的根节点,
  • 行②创建一个QStandardItem对象,表示一个数据项,
  • 行③将该数据项作为根节点的子节点添加到列表中。

行②的构造函数在内部调用该类的setData()函数,将行②的QString对象作为Qt::DisplayRole对应的数据子项存入新构造的对象。

由于数据集本身是一个列表,所以我们使用QListView显示该数据集,读者可以运行该例子查看显示结果。

代码段13-10:使用QStandardItemModel处理列表

    QStandardItemModel listModel;
QStandardItem *rootItem = listModel.invisibleRootItem(); // 行1
for (int row = ; row < ; ++row){
QStandardItem *item = new QStandardItem(QString("%1").arg(row) ); // 行2
rootItem->appendRow( item ); //行3
}
QListView listView;
listView.setModel ( & listModel );

2:如果数据集被表示为一个表格,可以调用类QStandardItemModel的成员函数setItem()设定表格中的某个数据项,如代码段13-11所示。

由于这个代码段中的数据集是一个表格,所以使用QTableView显示该数据集。

代码段13-11:使用QStandardItemModel处理表格

    QStandardItemModel tableModel(, );
for (int row = ; row < ; ++row){
for (int column = ; column < ; ++column) {
QStandardItem *item = new QStandardItem(QString("%0,%1").arg(row).arg(column));
tableModel.setItem(row, column, item);
}
}
QTableView tableView;
tableView.setModel( & tableModel );

3:如果数据集被表示为一个树,可以调用类QStandardItemModel的成员函数appendRow()向某个树节点添加子节点。

通过多次调用该函数,可以构建一棵复杂的树。代码段13-12构建一棵简单的树:最顶层的根节点有一个文字内容为“0”的子节点,

该子节点有一个文字内容为“1”的子节点。依此类推,“1”子节点有一个“2”子节点,“2”子节点有一个“3”子节点,形成一棵深度为4的树。

这棵树的每个节点都没有兄弟节点(具有相同父节点的多个节点被相互称为兄弟节点),感兴趣的读者可以修改这段代码,以使其中某些节点具有兄弟节点。

由于数据集是一棵树,我们使用QTreeView显示它。

代码段13-12,使用QStandardItemModel处理树:

QStandardItemModel treeModel;
QStandardItem *parentItem = treeModel.invisibleRootItem();
for (int i = ; i < ; ++i) {
QStandardItem *item = new QStandardItem(QString("%0").arg(i));
parentItem->appendRow(item);
parentItem = item;
}
QTreeView treeView;
treeView.setModel( & treeModel );

类QStandardItemModel之所以能够表示列表、表格、树甚至更复杂的数据结构,得益于类QStandardItem在其内部定义了一个类型为

QVector<QStandardItem*>的容器,可以将每个容器元素所指的QStandardItem对象设定为子对象。表现在如图13-13所示的类图上,类QStandardItem和自身具有“children”关系。一个类和自身发生关联,在UML中被称为自关联(self association)。类QStandardItemModel定义了一个名为root的数据成员,逻辑上是一个指向QStandardItem对象的指针。这个对象可以设定多个QStandardItem的对象作为自己的子对象,而其中每个子对象又可以包含其他的子对象。依此类推,这棵树可以具有任意深度,每个父对象可以包含任意多个子对象。

很自然地,QStandardItemModel可以使用QStandardItem表示具有树状数据结构的数据集,如图13-14所示。

图中的每个小方框表示类QStandardItem的一个对象。如果小方框的边线为虚,相应的QStandardItem对象并不表示数据集中的任何数据,仅被用来表示某种数据结构。如果小方框的边线为实,相应的QStandardItem对象就表示数据集中的一个数据项。在右侧的图中,QStandardItemModel的数据成员root所指的对象表示一个不可见的根,而数据集的根(图中结点G)被表示为这个不可见根的一个子节点。

列表被看作一个特殊的树:不可见根具有若干个子节点,每个子节点表示列表中的一个数据项,不再包含任何子节点,如该图左侧所示。

而表格的表示方式反而麻烦一些。不可见根含有若干子节点(图中A,B,C),这些子节点并不表示数据集中的任何数据项。

第i个子节点会包含若干子节点(比如图中D,E,F),这些子节点才表示表格第i行的数据项。

最后再讨论一下QStandardItemModel表示数据集的优缺点:

使用QStandardItemModel表示数据集具有以下优点:

  1. 该类使用QStandardItem存放数据项,用户不必定义任何数据结构来存放数据项;
  2. QStandardItem使用自关联关系,能够表达列表、表格、树甚至更复杂的数据结构,能够涵盖各种各样的数据集;
  3. QStandardItem本身存放着多个『角色,数据子项』,视图类、委托类或者其他用户定义的类能够方便地依据角色访问各个数据子项。

然而,这种表示方法也有局限性:

  • 当数据集中的数据项很多时,施加在数据集上的某些操作的执行效率会很低。

比如,设数据集是一个1万行、20列的表格,其中第10列存放的是浮点数。如果我们想计算这一列的平均值,按照图13-14,这需要遍历所有行,

取得第10列的QStandardItem对象,再依据角色“Qt::DisplayRole”取得对应的数据子项。由于这个数据子项的类型为QString,还需要将其转换为浮点数,

最后求所有浮点数的平均值。这些操作会耗费较长的时间。

因此,对于数据量不是很大、对性能要求不是很高的场合,我们可以使用类QStandardItemModel来表示一个数据集。

否则,用户应该从QAbstractItemModel、QAbstractListModel或者QAbstractTableModel派生新类,自行管理数据集的存放与访问。

Qt 常用类——QStandardItemModel的更多相关文章

  1. Qt学习之路(1)------Qt常用类用法说明

    Qt常用类 向控制台输出文本 第一个例子,我们采用STL的方式: console.cpp #include <iostream> int main() { std::cout <&l ...

  2. 【学习笔记】QT常用类及应用

    一.QT基类: QObject 二.QT中常用的库 QT中的类根据功能划分在不同的库中,在用户属性.pro文件中可以看到. 三.Qt基本对话框的使用 常用5类: 通过类名可以直接调用类的静态成员函数. ...

  3. Qt常用类——Qstring

    Qstring有一些方面跟C/C++中的string的使用,例如把一个字符串追加到另一个字符串中,也是用“+”.也有append函数等. 下面是是Qstring的一些常用的具体函数示例: Qt的QSt ...

  4. Qt常用类及类方法简介之 QAction类

    1.QAction::QAction ( const QString & text, QObject * parent )    QAction类的构造函数之一,利用text,parent创建 ...

  5. Qt常用类——QFrame类与QWidge类

    QFrame与QWidget的区别: QFrame是基本控件的基类,QWidget是QFrame基类. QWidget类是所有用户界面对象的基类. Widget是用户界面的基本单元:它从窗口系统接收鼠 ...

  6. Qt 常用类 (4)—— QPoint

    转载:落叶知秋时 QPoint 类代表一个坐标点,实现在 QtCore 共享库中.它可以认为是一个整型的横坐标和一个整型的纵坐标的组合. 构造 QPoint 类支持以下两种构造方式: QPoint() ...

  7. Qt常用类——QWidget

    QWidget类是所有用户界面对象的基类. Widget是用户界面的基本单元:它从窗口系统接收鼠标,键盘和其他事件,并在屏幕上绘制自己. 每个Widget都是矩形的,它们按照Z-order进行排序.

  8. Qt常用类——Qpoint

    QPoint 类代表一个坐标点,实现在 QtCore 共享库中.它可以认为是一个整型的横坐标和一个整型的纵坐标的组合. 构造 QPoint 类支持以下两种构造方式: QPoint(); // 构造横纵 ...

  9. Qt 中一些常用类中文说明

    Qt 中一些常用类中文说明是本文讲述的内容,这篇文章主要是介绍Qt 当中经常使用的类,采取的是使用字母索引的方式,下面的类是被经常使用的. QDataStream 为QIODevice提供了一串的二进 ...

随机推荐

  1. Prism5.0开发人员指南内容 Contents of the Developer's Guide to Prism Library 5.0 for WPF(英汉对照版)

    The Prism for WPF guide contains the following topics: Prism指南包含以下内容: Download and Setup Prism 下载并安装 ...

  2. L1-029 是不是太胖了

    据说一个人的标准体重应该是其身高(单位:厘米)减去100.再乘以0.9所得到的公斤数.已知市斤是公斤的两倍.现给定某人身高,请你计算其标准体重应该是多少?(顺便也悄悄给自己算一下吧……) 输入格式: ...

  3. Runtime-iOS运行时应用

    本篇将会总结Rutime的具体应用实例,结合其动态特性,Runtime在开发中的应用大致分为以下几个方面(Runtime应用图): 相关文章:iOS运行时Runtime基础 一.动态方法交换:Meth ...

  4. 玩转X-CTR100 l 平台-4WD智能小车

    我造轮子,你造车,创客一起造起来!更多塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍使用X-CTR100控制器搭建4WD智能 ...

  5. firefox下reset()不好使的问题

    最近在测试项目时发现,在firefox下,form.reset()方法对于隐藏的<input>等不起效果,导致程序中出现了错误,以下面为例: js代码: document.agentFor ...

  6. GSM中时隙、信道、突发序列、帧的解释

    刚从论坛中看到有人问GSM中时隙.信道.突发序列.帧知识.今天我们数字通信正好上到这一块,我就根据我知道的和网上搜索的回答! 1.时分多路复用技术 FDMA:频分多址 TDMA:时分多址 CDMA:码 ...

  7. windows form参数传递过程

    三.windows form参数传递过程 在Windows 程序设计中参数的传递,同样也是非常的重要的. 这里主要是通过带有参数的构造函数来实现的, 说明:Form1为主窗体,包含控件:文本框text ...

  8. Foundation--结构体

    一,NSRange typedef struct _NSRange { NSUInteger location; NSUInteger length; }NSRange; 这个结构体用来表示事物的一个 ...

  9. xgboost 简单测试

    #coding=utf8 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.f ...

  10. 正则表达式matcher.group()用法

    本帖转自http://winter8.iteye.com/blog/1463244 group是针对()来说的,group(0)就是指的整个串,group(1) 指的是第一个括号里的东西,group( ...