QT 模型/视图 编程 概述篇
模型/视图编程
模型/视图编程简介
Qt包含一组项目视图类,它们使用模型/视图体系结构来管理数据之间的关系以及数据呈现给用户的方式。此体系结构引入的功能分离为开发人员提供了更大的灵活性来自定义项的表示,并提供了标准的模型接口来允许与现有项视图一起使用广泛的数据源。在本文档中,我们简要介绍了模型/视图范式,概述了所涉及的概念,并描述了项目视图系统的体系结构。文中解释了体系结构中的每个组件,并给出了示例,说明如何使用提供的类。
模型/视图的体系结构
Model-View-Controller (MVC)是一种源自Smalltalk的设计模式,通常用于构建用户界面。在设计模式中,Gamma等人写道:
MVC由三种对象组成。模型是应用程序对象,视图是它的屏幕表示,控制器定义了用户界面对用户输入的反应方式。在MVC之前,用户界面设计倾向于将这些对象放在一起。MVC将它们解耦以增加灵活性和重用。
如果视图和控制器对象组合在一起,结果就是模型/视图体系结构。这仍然将数据的存储方式与呈现给用户的方式分开,但是提供了基于相同原则的更简单的框架。这种分离使得在几个不同的视图中显示相同的数据和实现新的视图类型成为可能,而不需要改变底层的数据结构。为了允许灵活地处理用户输入,我们引入了委托的概念。在此框架中使用委托的好处是,它允许自定义呈现和编辑数据项的方式。
模型/视图的体系结构
模型与数据源通信,为体系结构中的其他组件提供接口。通信的性质取决于数据源的类型和实现模型的方式。
视图从模型中获取模型索引;这些是对数据项的引用。通过向模型提供模型索引,视图可以从数据源检索数据项。
在标准视图中,委托呈现数据项。当一个项目被编辑时,委托直接使用模型索引与模型通信。
通常,模型/视图类可以分为上面描述的三个组:模型、视图和委托。这些组件中的每一个都是由提供公共接口的抽象类定义的,在某些情况下,还提供功能的默认实现。抽象类意味着子类化,以提供其他组件期望的全部功能;这还允许编写专门的组件。
模型、视图和委托使用信号和插槽彼此通信:
来自模型的信号通知视图关于数据源持有的数据的更改。
来自视图的信号提供有关用户与所显示项的交互的信息。
来自委托的信号在编辑期间用于告诉模型和视图编辑器的状态。
模型
所有项目模型都基于QAbstractItemModel类。该类定义了视图和委托用于访问数据的接口。数据本身不需要存储在模型中;它可以保存在由单独的类、文件、数据库或其他应用程序组件提供的数据结构或存储库中。
有关模型的基本概念在模型类一节中介绍。
QAbstractItemModel提供了一个数据接口,该接口足够灵活,可以处理以表、列表和树的形式表示数据的视图。但是,在为列表和类似表的数据结构实现新模型时,QAbstractListModel和QAbstractTableModel类是更好的起点,因为它们提供了公共函数的适当默认实现。每个类都可以被子类化,以提供支持特定类型列表和表的模型。
创建新模型一节将讨论模型的子类化过程。
Qt提供了一些现成的模型,可以用来处理项目的数据:
QStringListModel用于存储QString项的简单列表。
QStandardItemModel管理更复杂的项目树结构,每个项目可以包含任意数据。
QFileSystemModel提供关于本地文件系统中的文件和目录的信息。
QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel用于使用模型/视图约定访问数据库。
如果这些标准模型不满足您的需求,您可以子类化QAbstractItemModel、QAbstractListModel或QAbstractTableModel来创建您自己的自定义模型。
视图
对于不同类型的视图提供了完整的实现:QListView显示项列表,QTableView在表中显示来自模型的数据,QTreeView在层次结构列表中显示数据的模型项。每个类都基于QAbstractItemView抽象基类。尽管这些类是随时可用的实现,但它们也可以被子类化以提供定制的视图。
可用的视图将在视图类一节中进行讲述。
委托
QAbstractItemDelegate是模型/视图框架中委托的抽象基类。默认委托实现由QStyledItemDelegate提供,Qt的标准视图将其用作默认委托。然而,QStyledItemDelegate和QItemDelegate是绘画和为视图中的项目提供编辑器的独立替代方法。它们之间的区别是QStyledItemDelegate使用当前样式来绘制其项。因此,我们建议在实现自定义委托或使用Qt样式表时使用QStyledItemDelegate作为基类。
委托在委托类一节中进行了描述。
排序
在模型/视图架构中有两种处理排序的方法;选择哪种方法取决于您的基础模型。
如果你的模型是可排序的,i。如果它重新实现了QAbstractItemModel::sort()函数,那么QTableView和QTreeView都提供了一个API,允许您以编程方式对模型数据进行排序。另外,你还可以通过连接QHeaderView::sortIndicatorChanged()信号到QTableView::sortByColumn() slot或QTreeView::sortByColumn() slot来启用交互式排序(即允许用户通过点击视图的头信息对数据进行排序)。
另一种方法是,如果您的模型没有所需的接口,或者您想要使用列表视图来显示数据,那么在将数据显示在视图中之前,使用代理模型来转换模型的结构。这将在代理模型一节中详细讨论。
便捷类
从标准视图类派生出许多方便的类,以方便依赖于Qt的基于项的项视图和表类的应用程序。它们不打算被子类化。
此类的示例包括QListWidget、QTreeWidget和QTableWidget。
这些类不如视图类灵活,不能与任意模型一起使用。我们建议您使用模型/视图方法来处理项目视图中的数据,除非您非常需要一组基于项目的类。
如果您希望在使用基于项目的接口的同时利用模型/视图方法提供的特性,可以考虑使用视图类,如QListView、QTableView和QTreeView与QStandardItemModel。