Qt 学习之路 2(41):model/view 架构

有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应用程序的界面中。早期的 Qt 要实现这个功能,需要定义一个组件,在这个组件中保存一个数据对象,比如一个列表。我们对这个列表进行查找、插入等的操作,或者把修改的地方写回,然后刷新组件进行显示。这个思路很简单,也很清晰,但是对于大型程序,这种设计就显得苍白无力。比如,在一个大型系统中,你的数据可能很大,全部存入一个组件的数据对象中,效率会很低,并且这样的设计也很难在不同组件之间共享数据。如果你要几个组件共享一个数据对象,要么你就要用存取函数公开这个数据对象,要么你就必须把这个数据对象放进不同的组件分别进行维护。

Smalltalk 语言发明了一种崭新的实现,用来解决这个问题,这就是著名的 MVC 模型。对这个模型无需多言。MVC 是  Model-View-Controller 的简写,即模型-视图-控制器。在 MVC 中,模型负责获取需要显示的数据,并且存储这些数据的修改。每种数据类型都有它自己对应的模型,但是这些模型提供一个相同的 API,用于隐藏内部实现。视图用于将模型数据显示给用户。对于数量很大的数据,或许只显示一小部分,这样就能很好的提高性能。控制器是模型和视图之间的媒介,将用户的动作解析成对数据的操作,比如查找数据或者修改数据,然后转发给模型执行,最后再将模型中需要被显示的数据直接转发给视图进行显示。MVC 的核心思想是分层,不同的层应用不同的功能。

Qt 4 开始,引入了类似的 model/view 架构来处理数据和面向最终用户的显示之间的关系。当 MVC 的 V 和 C 结合在一起,我们就得到了 model/view 架构。这种架构依然将数据和界面分离,但是框架更为简单。同样,这种架构也允许使用不同界面显示同一数据,也能够在不改变数据的情况下添加新的显示界面。为了处理用户输入,我们还引入了委托(delegate)。引入委托的好处是,我们能够自定义数据项的渲染和编辑。

Model View 概览

如上图所示,模型与数据源进行交互,为框架中其它组件提供接口。这种交互的本质在于数据源的类型以及模型的实现方式。视图从模型获取模型索引,这种索引就是数据项的引用。通过将这个模型索引反向传给模型,视图又可以从数据源获取数据。在标准视图中,委托渲染数据项;在需要编辑数据时,委托使用直接模型索引直接与模型进行交互。

总的来说,model/view 架构将传统的 MV 模型分为三部分:模型、视图和委托。每一个组件都由一个抽象类定义,这个抽象类提供了基本的公共接口以及一些默认实现。模型、视图和委托则使用信号槽进行交互:

  • 来自模型的信号通知视图,其底层维护的数据发生了改变;
  • 来自视图的信号提供了有关用户与界面进行交互的信息;
  • 来自委托的信号在用户编辑数据项时使用,用于告知模型和视图编辑器的状态。

所有的模型都是QAbstractItemModel的子类。这个类定义了供视图和委托访问数据的接口。模型并不存储数据本身。这意味着,你可以将数据存储在一个数据结构中、另外的类中、文件中、数据库中,或者其他你所能想到的东西中。我们将在后面再详细讨论这些内容。

QAbstractItemModel提供的接口足够灵活,足以应付以表格、列表和树的形式显示的数据。但是,如果你需要为列表或者表格设计另外的模型,直接继承QAbstractListModelQAbstractTableModel类可能更好一些,因为这两个类已经实现了很多通用函数。关于这部分内容,我们也会在后文中详述。

Qt 内置了许多标准模型:

  • QStringListModel:存储简单的字符串列表。
  • QStandardItemModel:可以用于树结构的存储,提供了层次数据。
  • QFileSystemModel:本地系统的文件和目录信息。
  • QSqlQueryModelQSqlTableModelQSqlRelationalTableModel:存取数据库数据。

正如上面所说,如果这些标准模型不能满足你的需要,就必须继承QAbstractItemModelQAbstractListModel或者QAbstractTableModel,创建自己的模型类。

Qt 还提供了一系列预定义好的视图:QListView用于显示列表,QTableView用于显示表格,QTreeView用于显示层次数据。这些类都是QAbstractItemView的子类。这意味着,如果你要创建新的视图类,则可以继承QAbstractItemView

QAbstractItemDelegate
则是所有委托的抽象基类。自 Qt 4.4 依赖,默认的委托实现是QStyledItemDelegate。但是,QStyledItemDelegateQItemDelegate都可以作为视图的编辑器,二者的区别在于,QStyledItemDelegate使用当前样式进行绘制。在实现自定义委托时,推荐使用QStyledItemDelegate作为基类,或者结合 Qt style sheets。

如果你觉得 model/view 模型过于复杂,或者有很多功能是用不到的,Qt 还有一系列方便使用的类。这些类都是继承自标准的视图类,并且继承了标准模型。这些类并不是为其他类继承而准备的,只是为了使用方便。它们包括QListWidgetQTreeWidgetQTableWidget。这些类远不如视图类灵活,不能使用另外的模型,因此只适用于简单的情形。

Qt 学习之路 2(41):model/view 架构的更多相关文章

  1. Qt学习之路(45): 自定义model之一

    前面我们说了Qt提供的几个预定义model.但是,面对变化万千的需求,那几个model是远远不能满足我们的需要的.另外,对于Qt这种框架来说,model的选择首先要能满足绝大多数功能的需要,这就是说, ...

  2. Qt学习之路:自定义Model三篇,自定义委托等等

    http://devbean.blog.51cto.com/448512/d-8/p-2

  3. Qt 学习之路 2(31):贪吃蛇游戏(1)

    Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...

  4. Qt 学习之路 2(30):Graphics View Framework

    Qt 学习之路 2(30):Graphics View Framework 豆子 2012年12月11日 Qt 学习之路 2 27条评论 Graphics View 提供了一种接口,用于管理大量自定义 ...

  5. 第15.23节 PyQt(Python+Qt)入门学习:Model/View架构中QListView视图配套Model的开发使用

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 QListView理论上可以和所有QAbstractItemModel派生的类如QStri ...

  6. 第15.22节 PyQt(Python+Qt)入门学习:Model/View架构详解

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.简介 在PyQt和Qt中,Model/View架构是图形界面开发时用于管理数据和界面展现方式的关 ...

  7. 第15.18节 PyQt(Python+Qt)入门学习:Model/View架构中视图Item Views父类详解

    老猿Python博文目录 老猿Python博客地址 一.概述 在PyQt图形界面中,支持采用Model/View架构实现数据和界面逻辑分离,其中Model用于处理数据存储,View用于界面数据展现,当 ...

  8. PyQt(Python+Qt)学习随笔:model/view架构中类QStandardItemModel的使用方法

    老猿Python博文目录 老猿Python博客地址 一.概述 QStandardItemModel是QAbstractItemModel的派生类,用于在Model/View架构中存储自定义数据的通用模 ...

  9. PyQt(Python+Qt)学习随笔:Model/View架构中的Model模型概念

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Model/View架构中的Model模型Model与数据源通信,为体系结构中的其他组件提供数据接口 ...

随机推荐

  1. python闭包和装饰器的理解

    闭包: 两个函数的嵌套,外部函数返回内部函数的引⽤,外部函数⼀定有参数 def 外部函数(参数): def 内部函数(): pass return 内部函数 他跟函数之间的区别: 1.格式两个函数嵌套 ...

  2. Linux的基本指令--

     VIM简介: Vi有三种基本工作模式 1.命令模式 2.文本输入模式 3. 末行模式 VIM基本操作: 一 . 进入插入模式: i: 插入光标前一个字符 I: 插入行首 a: 插入光标后一个字符 A ...

  3. 2-1 CPU多级缓存-缓存一致性.mkv

  4. 【bzoj1017】[JSOI2008]魔兽地图DotR

    1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1658  Solved: 755[Submit][S ...

  5. Solidity智能合约升级解决方案

    https://blog.zeppelin.solutions/proxy-libraries-in-solidity-79fbe4b970fd

  6. 目录、目录项、文件名、inode、软硬链接的关系

    对于Unix系列的操作系统,大多都有v节点.但是对于linux来说,只有通用的i节点,却没有v节点. 下面来探讨一下,linux下的i节点. linux中,文件查找不是通过文件名称来查找的.实际上是通 ...

  7. ShopNc实例化对象

    1.模型 $model_member = Model('member'); 2.接口 require_once BASE_ROOT_PATH.'/member/api/smiMember/action ...

  8. 实践作业3:白盒测试----findbugs介绍及使用DAY7

    本小组选择的是一个开源的Java静态代码分析工具----Findbugs. 与其他静态分析工具(如Checkstyle和PMD)不同,FindBugs 不注重样式或者格式,它专注于寻找真正的缺陷或者潜 ...

  9. Robot Framework - 常用断言讲解

    RobotFramework带有丰富的系统关键,使用时无需导入,直接使用,为写自动化用例带来了极大的方便:不能停留在知道或者是会得程度,只有熟练使用各关键字,才能提升自动化用例的写作效率. 下面将逐个 ...

  10. UIWebView分页显示

    問題:使用iOS UIWebView時,載入本地html檔案,但是該檔案太大,結果螢幕畫面形成一長條型顯示,雖然用滾動畫面可以看見整個html檔案,但是滑來滑去,不好用. 目標:用UIWebView載 ...