Qt模型讲解

在 model/view 架构中,model 提供一种标准接口,供视图和委托访问数据。在 Qt 中,这个接口由 QAbstractItemModel 类进行定义。不管底层数据是如何存储的,只要是 QAbstractItemModel 的子类,都提供一种表格形式的层次结构。视图利用统一的转换来访问模型中的数据。但是,需要提供的是,尽管模型内部是这样组织数据的,但是并不要求也得这样子向用户展示数据。

下面是各种 model 的组织示意图。我们利用此图来理解什么叫 “一种表格形式的层次结构”。

如上图所示,List Model 虽然是线性的列表,也有一个 Root Item(根节点),之下才是呈线性的一个个数据,而这些数据实际可以看作是一个只有一列的表格,但是它是有层次的,因为有一个根节点。Table Model 就比较容易理解,只是也存在一个根节点。Tree Model 主要面向层次数据,而每一层次都可以都很多列,因此也是一个带有层次的表格。

为了能够使得数据的显示同存储分离,我们引入模型索引(model index)的概念。通过索引,我们可以访问模型的特定元素的特定部分。视图和委托使用索引来请求所需要的数据。由此可以看出,只有模型自己需要知道如何获得数据,模型所管理的数据类型可以使用通用的方式进行定义。索引保存有创建的它的那个模型的指针,这使得同时操作多个模型成为可能。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

QAbstractItemModel *model = index.model();

模型索引提供了所需要的信息的临时索引,可以用于通过模型取回或者修改数据。由于模型随时可能重新组织其内部的结构,因此模型索引很可能变成不可用的,此时,就不应该保存这些数据。如果你需要长期有效的数据片段,必须创建持久索引。持久索引保证其引用的数据及时更新。临时索引(也就是通常使用的索引)由 QModelIndex 类提供,持久索引则是 QPersistentModelIndex 类。

为了定位模型中的数据,我们需要三个属性:行号、列号以及父索引。下面我们对其一一进行解释。

我们前面介绍过模型的基本形式:数据以二维表的形式进行存储。此时,一个数据可以由行号和列号进行定位。注意,我们仅仅是使用 “二维表” 这个名词,并不意味着模型内部真的是以二维数组的形式进行存储;所谓 “行号”“列号”,也仅仅是为方便描述这种对应关系,并不真的是有行列之分。通过指定行号和列号,我们可以定位一个元素项,取出其信息。此时,我们获得的是一个索引对象(回忆一下,通过索引我们可以获取具体信息):

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

模型提供了一个简单的接口,用于列表以及表格这种非层次视图的数据获取。不过,正如上面的代码暗示的那样,实际接口并不是那么简单。我们可以通过文档查看这个函数的原型:

QModelIndex QAbstractItemModel::index(int row,
                                      int column,
                                      const QModelIndex &parent=QModelIndex()) const

这里,我们仅仅使用了前两个参数。通过下图来理解一下:

在一个简单的表格中,每一个项都可以由行号和列号确定。因此,我们只需提供两个参数即可获取到表格中的某一个数据项:

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

函数的最后一个参数始终是 QModelIndex (),接下来我们就要讨论这个参数的含义。

在类似表格的视图中,比如列表和表格,行号和列号足以定位一个数据项。但是,对于树型结构,仅有两个参数就不足够了。这是因为树型结构是一个层次结构,而层次结构中每一个节点都有可能是另外一个表格。所以,每一个项需要指明其父节点。前面说过,在模型外部只能用过索引访问内部数据,因此,index() 函数还需要一个 parent 参数:

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

类似的,我们来看看下面的示意图:

图中,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);

由此我们看到,如果只有行号和列号两个参数,B 的行号是 1,列号是 0,这同与 A 同级的行号是 1,列号是 0 的项相同,所以我们通过 parent 属性区别开来。

以上我们讨论了有关索引的定位。现在我们来看看模型的另外一个部分:数据角色。模型可以针对不同的组件(或者组件的不同部分,比如按钮的提示以及显示的文本等)提供不同的数据。例如,Qt::DisplayRole 用于视图的文本显示。通常来说,数据项包含一系列不同的数据角色,这些角色定义在 Qt::ItemDataRole 枚举中。

我们可以通过指定索引以及角色来获得模型所提供的数据:

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

通过为每一个角色提供恰当的数据,模型可以告诉视图和委托如何向用户显示内容。不同类型的视图可以选择忽略自己不需要的数据。当然,我们也可以添加我们所需要的额外数据。

总结一下:

  • 模型使用索引来提供给视图和委托有关数据项的位置的信息,这样做的好处是,模型之外的对象无需知道底层的数据存储方式;
  • 数据项通过行号、列号以及父项三个坐标进行定位;
  • 模型索引由模型在其它组件(视图和委托)请求时才会被创建;
  • 如果使用 index() 函数请求获得一个父项的可用索引,该索引会指向模型中这个父项下面的数据项。这个索引指向该项的一个子项;如果使用 index() 函数请求获得一个父项的不可用索引,该索引指向模型的最顶级项;
  • 角色用于区分数据项的不同类型的数据。

下面回到前面我们曾经见过的模型 QFileSystemModel,看看如何从模型获取数据。

QFileSystemModel *model = new QFileSystemModel;
QModelIndex parentIndex = model->index(QDir::currentPath());
int numRows = model->rowCount(parentIndex);

在这个例子中,我们创建了 QFileSystemModel 的实例,使用 QFileSystemModel 重载的 index() 获取索引,然后使用 rowCount() 函数计算当前目录下有多少数据项(也就是行数)。前面一章中迷迷糊糊的代码,现在已经相当清楚了。

为简单起见,下面我们只关心模型第一列。我们遍历所有数据,取得第一列索引:

for (int row = 0; row < numRows; ++row) {
    QModelIndex index = model->index(row, 0, parentIndex);

我们使用 index() 函数,第一个参数是每一行行号,第二个参数是 0,也就是第一列,第三个参数是 parentIndex,也就是当前目录作为父项。我们可以使用模型的 data() 函数获取每一项的数据。注意,该函数返回值是 QVariant,实际是一个字符串,因此我们直接转换成 QString:

    QString text = model->data(index, Qt::DisplayRole).toString();
    // 使用 text 数据
}

上面的代码片段显示了从模型获取数据的一些有用的函数:

  • 模型的数目信息可以通过 rowCount() 和 columnCount() 获得。这些函数需要制定父项;
  • 索引用于访问模型中的数据。我们需要利用行号、列号以及父项三个参数来获得该索引;
  • 当我们使用 QModelIndex() 创建一个空索引使用时,我们获得的就是模型中最顶级项;
  • 数据项包含了不同角色的数据。为获取特定角色的数据,必须指定这个角色。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt5是一款跨平台的应用程序框架,适用于Windows、Linux、macOS和Android等多种操作系统。提供了诸如GUI、网络、数据库、XML、音频、视频等多个领域的丰富功能,因此成为开发人员常用的工具之一。 如何学习Qt5呢?首先,需要掌握C++编程语言,对于没有基础的人来说,需要先学习C++基础语法。其次,需要安装并配置好Qt5开发环境,包括Qt Creator IDE和Qt Framework等。安装完成后,就可以开始进行Qt5的编程学习了。 Qt5入门教程主要内容包括:Qt5的基本概念和常用组件, Qt对象模型和信号槽机制,界面设计和布局,窗口管理和事件处理等方面。在实践中,可以通过编写一些小型的应用程序来巩固所学内容。例如实现一个简单的文本编辑器、图像浏览器,模拟一个简单的计算器等。 在学习过程中,需要注意一些常见的问题。例如,Qt对象的生命周期、信号槽的连接方式、事件处理的优先级等都需要注意。另外,Qt5的文档和示例非常丰富,开发者可以通过查阅官方文档和代码示例来更好地理解Qt5的使用方法和特点。 总之,Qt5是一款功能强大的开发框架,适合从事图形界面开发、嵌入式开发、游戏开发等多个领域。学习Qt5需要掌握C++编程语言、熟悉Qt5的各种组件和特性,并进行实践。通过不断的学习和实践,开发者可以在Qt5框架下开发出高质量的应用程序。 ### 回答2: Qt是一种跨平台的C++应用程序开发框架。Qt5提供了许多新的特性和改进,如QML、Qt Quick、Qt Quick Controls和Qt WebEngine等。对于新手,Qt5入门教程非常重要,因为它可以帮助他们快速上手并深入了解框架。 Qt5入门教程详细讲解版应该包括以下内容: 1.安装和设置Qt5:介绍不同平台上的安装步骤和必需的设置。 2.基本概念:介绍概念,如信号和槽、对象型、元对象系统和Qt应用程序的生命周期等。 3.第一个Qt5应用程序:创建一个Hello World应用程序并解释基本的代码架构。介绍Qt Creator集成开发环境的使用步骤。 4.Qt5界面设计:介绍QML、Qt Quick和Qt Quick Controls,这些特性可用于创建现代和响应式的应用程序界面。 5.数据持久性:介绍如何使用Qt5框架中的SQLite、MySQL和PostgreSQL等来实现数据持久性。 6.QWidget和QMainWindow:将介绍如何使用QWidget和QMainWindow类来创建桌面应用程序界面,添加菜单和栏,应用程序状态栏和工具栏。 7.调试和部署:说明如何调试和部署Qt应用程序。 总之,Qt5入门教程详细讲解版旨在帮助新手更好地了解Qt5框架并开始创建跨平台的应用程序。 ### 回答3: Qt5是一款流行的开源跨平台应用程序开发框架,用于构建桌面,移动和嵌入式应用程序。它支持多种编程语言,例如C ++,Python和JavaScript。本教程将详细讲解如何使用Qt5开始开发应用程序。 Qt5入门教程C++语言为基础进行讲解,首先阐述了Qt5的工作原理和基本架构。之后,教程介绍了如何建立一个Qt5应用程序开发环境,并详细阐述了Qt Creator的功能和用法。接着,通过一个简单的“Hello World”应用程序示例,该教程介绍了Qt5的界面设计和常用控件的使用方式。 在基础知识介绍之后,本教程深入探讨了Qt5的核心构件,例如Qt Widgets,Qt Quick和Qt WebEngine。通过这些构件的讲解,学习者将会掌握如何在Qt5中创建各种用户界面。 本教程还包括有关处理Qt5信号和槽机制、自定义控件以及在Qt5应用程序中使用外部库的介绍。此外,教程详细讲解了如何调试和部署Qt5应用程序,并介绍了Qt5的一些高级功能,例如Qt Multimedia和Qt OpenGL。 总的来说,本教程非常详细,包含丰富的示例和练习,可以帮助初学者快速上手使用Qt5来开发各种类型的应用程序。无论您是想学习Qt5的初学者,还是有经验的开发人员,该教程都不容错过。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值