当前位置 博文首页 > Allen Roson:QT Model Classes
目录
?
基本概念
模型索引
行和列
项目的父级
项目角色
摘要
在模型/视图体系结构中,模型提供了一个标准接口,视图和委托使用该接口访问数据。在Qt中,标准接口由QAbstractItemModel?类定义。无论数据项如何存储在任何底层数据结构中,QAbstractItemModel?的所有子类都将数据表示为包含项表的层次结构。视图使用此约定访问模型中的数据项,但它们向用户显示此信息的方式不受限制。
?
模型还通过signals和slots机制通知任何附加视图有关数据的更改。
本节介绍一些基本概念,这些概念是其他组件通过模型类访问数据项的方式的核心。更高级的概念将在后面的章节中讨论。
为了确保数据的表示与访问方式保持分离,引入了模型索引的概念。通过模型可以获得的每一条信息都由一个模型索引表示。视图和委托使用这些索引请求要显示的数据项。
因此,只有模型需要知道如何获取数据,并且模型管理的数据类型可以相当一般地定义。模型索引包含指向创建它们的模型的指针,这可以防止在处理多个模型时出现混淆。
QAbstractItemModel *model = index.model();
模型索引提供对信息片段的临时引用,并可用于通过模型检索或修改数据。由于模型可能会不时地重新组织其内部结构,因此模型索引可能会变得无效,因此不应存储。如果需要对一段信息进行长期引用,则必须创建持久模型索引。这为模型保持最新的信息提供了参考。临时模型索引由QModelIndex类提供,持久模型索引由QPersistentModelIndex类提供。
要获得与数据项对应的模型索引,必须为模型指定三个属性:行号、列号和父项的模型索引。以下各节将详细描述和解释这些属性。
在其最基本的形式中,模型可以作为一个简单的表来访问,其中的项通过它们的行号和列号来定位。这并不意味着底层数据块存储在数组结构中;使用行号和列号只是允许组件相互通信的约定。我们可以通过向模型指定任何给定项的行号和列号来检索有关该项的信息,然后我们会收到一个表示该项的索引:
QModelIndex index = model->index(row, column, ...);
为简单的单级数据结构(如列表和表)提供接口的模型不需要提供任何其他信息,但正如上面的代码所示,我们需要在获取模型索引时提供更多信息。
?
当在表或列表视图中使用数据时,模型提供的项目数据的表式接口是理想的;行和列编号系统精确地映射到视图显示项目的方式。但是,树视图等结构要求模型向其中的项公开更灵活的接口。因此,每个项也可以是另一个项表的父项,就像树视图中的顶级项可以包含另一个项列表一样。
在为模型项请求索引时,必须提供有关该项父项的一些信息。在模型之外,引用项的唯一方法是通过模型索引,因此还必须给出父模型索引:
QModelIndex index = model->index(row, column, parent);
?
模型中的项可以为其他组件执行各种角色,允许为不同的情况提供不同类型的数据。例如,Qt::DisplayRole用于访问可以在视图中显示为文本的字符串。通常,项包含许多不同角色的数据,标准角色由Qt::ItemDataRole定义。
我们可以通过向模型传递与该项对应的模型索引,并通过指定角色来获取所需的数据类型,从而向模型请求该项的数据:
QVariant value = model->data(index, role);
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);
为了获得一个模型索引,我们为我们想要的所有项的父项指定行号、列号(第一列为零)和适当的模型索引。使用模型的data()函数检索存储在每个项中的文本。我们指定模型索引和DisplayRole,以获取字符串形式的项数据。
QString text=model->data(index,Qt::DisplayRole).toString();
//在小部件中显示文本。
}
上面的示例演示了从模型中检索数据的基本原则:
可以使用rowCount()和columnCount()找到模型的维度。这些函数通常需要指定父模型索引。
模型索引用于访问模型中的项。需要行、列和父模型索引来指定项。
要访问模型中的顶级项,请使用QModelIndex()将空模型索引指定为父索引。
项包含不同角色的数据。要获取特定角色的数据,必须向模型提供模型索引和角色。
进一步阅读
通过实现qabstractemmodel提供的标准接口,可以创建新的模型。在creatingnewmodels部分,我们通过创建一个方便的现成模型来展示这一点,该模型用于保存字符串列表。