转载:落叶知秋时

类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. Android中aar和jar文件的认识

    在Android开发中,我们总是会引入其他第三方的库或者资源等,有时候是添加一个jar文件,有时候添加一个aar文件,那么这两种类型的文件有什么区别吗?详情请看下文. 一.描述. 1.   *.jar ...

  2. 《Python》 property、classmethod、staticmethod、isinstance、issubclass

    一.property property是一个装饰器函数 装饰器函数的使用方法:在函数.方法.类的上面一行直接@装饰器的名字 装饰器的分类: 1.装饰函数 2.装饰方法:property 3.装饰类 i ...

  3. php 函数2

  4. JSP--TOMCAT-MYSQL web页面删除

    deleteStudentjsp.jsp页面代码 <%@ page language="java" contentType="text/html; charset= ...

  5. 如何从ie11降到ie9

    如果你是win7,中间没有安装过IE10的话,在系统已安装的更新中找到IE11右键卸载后就会回滚到IE9. ie11浏览器现在win7和win8版本的都已经发布了;但是因为一些12306火车票订票网站 ...

  6. caffe测试mnist问题-error while loading shared libraries

    问题描述 build/examples/mnist/convert_mnist_data.bin: error while loading shared libraries: libcudart.so ...

  7. Springboot整合pagehelper分页

    一.在pom中添加依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId&g ...

  8. Spring如何解析XML文件——Spring源码之XML初解析

    首先,在我的这篇博客中已经说到容器是怎么初步实现的,并且要使用XmlBeanDefinitionReader对象对Xml文件进行解析,那么Xml文件是如何进行解析的,将在这片博客中进行一些陈述. 数据 ...

  9. BZOJ5091: [Lydsy1711月赛]摘苹果【期望DP】

    Description 小Q的工作是采摘花园里的苹果.在花园中有n棵苹果树以及m条双向道路,苹果树编号依次为1到n,每条道路的两 端连接着两棵不同的苹果树.假设第i棵苹果树连接着d_i条道路.小Q将会 ...

  10. linux环境下编译php扩展

    1.使用ext_skel工具生成扩展框架 ./ext_skel --extname=myext 2.编辑config.m4文件 cd myext/vim config.m4 去掉以下内容的注释: PH ...