Qt 模型类 (转)

摘要:
在模型/视图体系结构中,模型为视图和代理提供了访问数据的标准接口。为了确保数据的表示和访问数据的方式是独立的,引入了模型索引的概念。QAbstractItemModel*model=index.model();模型索引提供了对信息片段的临时引用,可用于通过模型获取或修改数据。临时模型索引由QModelIndex类提供,持久模型索引由QPersistModelIndex类提供。

在模型/视图架构中,模型提供一个标准的接口供视图和委托(view/delegate)用来访问数据。在Qt中,这个标准的接口是由类QAbstractItemModel定义的。无论底层数据结构中的数据是如何存储的,类QAbstractItemModel的所有子类都将数据表示为一个包含由数据项组成的表格的层次型结构。视图按照这个约定来访问模型中的数据项,但是它们将信息展示给用户的时候不需要这样来做。

Qt 模型类 (转)第1张

模型也使用信号和信号槽机制来向关联的视图通知关于数据的变化。

模型索引

为了确保数据的表示与数据被访问的方式是分开独立的,引入了模型索引(modelindex)的概念。每一个可以通过模型来获取的信息都被一个模型索引来表示。视图和委托使用这些模型索引来获取要显示的数据项(视图/委托操作的不是数据项,实际上操作的是保存了数据项内容的模型索引)。

结果是,只有模型需要知道如何获取数据,并且被该模型管理的数据的种类可以进行很广泛的定义。模型索引包含一个指向创建它们(模型索引)的模型的指针,这一点避免了在使用不止一个模型来工作时所产生的混乱。

QAbstractItemModel *model = index.model();

模型索引提供对信息片段的临时引用,可以被用来通过模型获取或者修改数据。由于模型可能会重新组织它们内部的数据结构,因此模型索引可能会失效,所 以不应当被保存。 如果你需要对一个信息片段的长期的引用,那么你必须创建一个持久模型索引。这样就提供了一个指向模型所维护的最新数据的引用。临时模型索引由 QModelIndex类提供,持久模型索引由QPersistentModelIndex类提供。

要获得对应于某一个数据项的模型索引,需要告诉模型3个属性:1个行号,1个列号,和父数据项的模型索引。接下来的小节描述及详细解释这些属性。

行与列

在最基本的形式下,一个模型可以被当作一个简单的表格来访问,在这个表格中数据项是通过行号和列号来定位的。这并不是说底层的数据片段存储在一个 矩阵结构中;行号和列号的使用只是一个用来让部件之间进行通信的约定。我们可以通过向模型提供任意指定的项目的行号和列号来获取它的信息,我们会获得一个 表示该数据项的模型索引:

QModelIndex index = model->index(row, column, …);

那些为简单、单级的数据结构,例如列表和表格提供接口的模型不需要任何其它的信息,但是,正如上面的代码所显示的,我们在获取一个模型索引时需要提供更多的信息。

Qt 模型类 (转)第2张

这个示意图展示了一个基本的表格模型,其中每个数据项都是通过一对行号和列号来定位的。我们通过向模型传递一个数据项的对应的行号和列号来获取一个指向该项目的索引。

QModelIndex indexA = model->index(0, 0, QModelIndex());

QModelIndex indexB = model->index(1, 1, QModelIndex());

QModelIndex indexC = model->index(2, 1, QModelIndex());

模型中的顶层数据项都是通过以QModelIndex()作为它们的父对象项目来引用的。这一点是在下一节描述的。

 

数据项的父对象

模型针对数据项提供的类似表格的接口完美适用于在表格或者列表视图中使用数据;行号和列号系统准确地与视图显示项目的方式对应。然而,像树视图这样的结构要求模型针对它管理的项目展现出一个更灵活的接口。结果是,每个数据项也可以作为另一个数据项组成的表格的父对象,就像树视图中的一个顶层数据项可以包含另一个由数据项组成的列表一样。

当我请求一个模型数据项的模型索引时,我位必须提供一些关于它的父对象的信息。在模型之外,指向一个项目的唯一的方法就是使用一个模型索引,所以一个父对象模型索引也必须被给出:

QModelIndex index = model->index(row, column, parent);

Qt 模型类 (转)第3张

父对象,行和列

这个图显示的是一个树模型的表示方式,其中,每个数据项是使用一个父对象、一个行号和一个列号来索引的。

项目“A”和“C”在模型中是被以顶级的兄弟节点的方式来表示的:

QModelIndex indexA = model->index(0, 0, QModelIndex());

QModelIndex indexC = model->index(2, 1, QModelIndex());

项目“A”有一些子对象。项目“B”的模型索引是以下面的代码来获取的:

QModelIndex indexB = model->index(1, 0, indexA);

 

数据项角色

一个模型中的数据项可以为其它部件扮演各种各样的角色,以便为不同的情况来使用不同种类的数据。例如,Qt::DisplayRole用来在一个视图中获取一个可以被当成文本显示的字符串。一般地,数据项都包含了用于很多不同角色的数据,而标准的角色是被Qt::ItemDataRole定义的。

我们可以通过向模型传递对应于一个数据项的模型索引来获取它的数据,并且通过指定一个角色来获取我们想要的类型的数据:

QVariant value = model->data(index, role);

Qt 模型类 (转)第4张

数据项角色

角色指示模型哪种类型的数据是我们想要的。视图可以以不同的方式来显示不同的角色,所以为每个角色提供合适的信息是很重要的。

创建新的模型一节更加具体地讲述了关于角色的一些特殊用法。

数据项数据的最常用的用法是被Qt::ItemDataRole中定义的标准角色描述的。通过为每个角色提供适当的数据项数据,模型可以为视图和委托提供关于数据项该如何显示给用户的提示。不同的视图可以自主选择是按照要求来忽略这个提示还是遵从这个提示。也可以定义附加的角色,以用于实现应用程序特定的目的。

概念的总结

  • •.模型索引以一种不依赖于任何底层数据结构的方式来向视图和委托提供关于模型所提供的数据项的位置的信息。
  • •.数据项是通过行号、列号和它们的父对象的模型索引来引用的。
  • •.模型索引是模型在其它组件,例如视图和委托的请求下构造的。
  • •.如果在使用index()来请求模型索引时,一个有效的模型索引被当作父项目的索引来指定,那么返回的索引将会指向模型中在该父数据项下方的一个子数据项。获取的模型索引指向那个父数据项的一个子数据项。
  • •.如果在使用index()来请求索引时,一个无效的模型索引被当作父数据项的模型索引来指定,那么返回的索引将会指向模型中的一个顶层数据项。
  • •.角色区分与一个数据项结合的不同类型的数据。

使用模型索引

为了演示如何使用模型索引来从模型中取得数据,我们设置一个没有视图的QFileSystemModel,并且在一个部件中显示文件和目录的名字。尽管这没有展示出一个使用模型的标准方式,但是它展示了使用模型索引时在模型中使用的一些约定。

我们以下面的方式来构造一个文件系统模型:

QFileSystemModel *model = new QFileSystemModel;

QModelIndex parentIndex = model->index(QDir::currentPath());

int numRows = model->rowCount(parentIndex);

在这种情况下,我们建立一个默认的QFileSystemModel,使用该模型提供的特定的index()实现来获取一个父对象索引,再使用函数rowCount()来统计该模型中的行数。

简便起见,我们只关心该模型中第一列的项目。我们按顺序检查每一行,获取每一行中第一个项目的模型索引,再读取模型中为该项目储存的数据。

for (int row = 0; row < numRows; ++row) {

QModelIndex index = model->index(row, 0, parentIndex);

为了获得一个模型索引,我们指定行号、列号(为第一列指定为0),以及针对所有我们想要获取的项目的父项目的合适的模型索引。保存在每个项目中的文本是使用模型的data()函数来获取的。我们指定模型索引和DisplayRole以便以字符串的形式来获取该项目的数据。

QString text = model->data(index, Qt::DisplayRole).toString();

// Display the text in a widget.

}

上面的例子展示了从模型中获取数据时所用的基本原则:

  • •.一个模型的维度可以使用rowCount()和columnCount()来获取。这些函数通常要求指定一个父模型索引。
  • •.模型索引用来访问模型中的项目。要指定一个项目,需要行号、列号和父模型索引。
  • •.要访问模型中的顶级项目,需要使用QModelIndex()来指定一个空的模型索引作为父索引。
  • •.项目都包含针对不同角色的数据。为了获取一个指定角色的数据,必须同时向模型提供模型索引和角色。

免责声明:文章转载自《Qt 模型类 (转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇代码服务器运行时找不到包文件位置Kotlin Vertx下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Elasticsearch与MySQL对应关系表

MySQL 中的数据库(DataBase),等价于 ES 中的索引(Index)。 MySQL 中一个数据库下面有 N 张表(Table),等价于1个索引 Index 下面有 N 多类型(Type)。 MySQL 中一个数据库表(Table)下的数据由多行(Row)多列(column,属性)组成,等价于1个 Type 由多个文档(Document)和多...

sql server百万级别数据量 农码一生

1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数...

Delphi学习笔记(精华二)

RichEdit1.ScrollBars 选择滚动条,ssNone[无],ssHorizontal[只有水平],ssVertical[只有垂直],ssBoth[同时有水平和垂直]RichEdit1.SelStart RichEdit1.SelLength 选中文本的起始位置和长度RichEdit1.SelText 选中的文本FindDialog.Find...

MySQL:全文本和 Bool 文本检索

全文本检索 之前我们使用的通配符或正则表达式进行对关键字的检索,效果很好,但是还是有一些不足的。首先是这样的检索就需要对所有的行进行检索,那么当数据量过多时就会带来性能问题。第二是这样的检索都是完全匹配的,对于模糊查找或者是部分索引而言,没有很强大的功能。这个时候我们就需要更为智能的检索方式,一种不错的选择是使用全文本搜索。全文本搜索有以下注意事项: 被...

记一次数据库的优化

前几天公司应用后台更新版本,晚上发版,测试 到了12点过,测试的差不多没有问题,其他同事都回家了,我和所谓的主管(要好的朋友)不想回去了,就留在的公司过夜。 第二天起来,我戳了一眼,没有问题,结果到了8点多,团队群里就报登录界面显示不了验证码。(登录需要输入验证码) 迅速的就开始进行问题的检查,因为是验证码无法显示,于是就定位到处理登录的工程account...

Elastic Stack之搜索引擎基础

Elastic Stack之搜索引擎基础 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 一.搜索引擎概述 1>.什么是搜索引擎 搜索引擎(Search Engine)是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。搜索引擎包括全文索引、...