我们的系统有很多数据显示的需求,比如从数据库中把数据取出,然后以自己的方式显示在我们自己的应用程序的界面中。进行这一操作的典型方式是使用Qt的Item View类。
在早期的Qt版本中,要实现这个功能,我们需要定义一个widget,然后在这个widget中保存一个数据对象,比如是个list,然后我们对这个list进行查找、插入等的操作,或者把修改的地方写回这个list,然后刷新widget进行显示。这个思路很简单,也很清晰,但是对于大型程序,这种设计就显得苍白无力。比如,在一个大型系统中,你的数据可能很大,如果全部存入一个widget的数据对象中,效率会很低,并且这样的设计也很难在widgets之间共享变量,也就是说,如果你要几个组件共享一个数据对象,要么你就要用getter函数公开这个数据对象,要么你就必须把这个数据对象放进不同的组件分别进行维护。
Smalltalk语言发明了一种崭新的实现,用来解决这个问题,这就是著名的MVC模型。对这个模型无需多言,简单来说,这是一个model-view-controller模型,即模型-视图-控制器。在MVC中,模型负责获取需要显示的数据,并且能够存储这些数据的修改。每种数据类型都有它自己对应的模型,但是这些模型提供一个相同的API,用于隐藏内部实现。视图用于将模型数据显示给用户。对于很大的数据,或许只显示一小部分,这样就能很好的提高性能。控制器是模型和视图之间的媒介,将用户的动作解析成对数据的操作,比如查找数据或者修改数据,然后转发给模型执行,最后再将模型中需要被显示的数据直接转发给视图进行显示。
对于Qt而言,它使用的是一个类似于MVC模型的model-view架构。其中,model就相当于MVC架构中的model,而对于控制器部分,Qt使用的是另外的一种抽象,代理delegate。代理被用来提供对item渲染和编辑的控制。对于每种视图,Qt都提供了一个默认的代理,对于大多数应用来说,我们只需要使用这个默认的代理即可。这其中的类关系如下图所示(出自C++ GUI Programming with Qt 4, 2nd Edition)
![](https://i-blog.csdnimg.cn/blog_migrate/b019b7c8cd76dfc129be63eddd23afe8.png)
使用Qt的model-view架构,我们可以让model是取回view所要展示的数据,这样就可以在不降低性能的情形下处理大量数据。并且你可以把一个model注册给多个view,让这些view能够显示同样的数据,也就是为同一个数据提供不同的显示方式。Qt会自动地对这些view保持同步,自动刷新所有的view以显示最新的数据。这样,我们就可以只对model进行修改,view会自动更新。
在少量数据的情形下,我们不需要动用model这样重量级的组件。Qt为了方便起见也提供了item view类,分别是QListWidget,QTableWidget和QTreeWidget,使用这些类可以直接对item进行操作。这种实现很像Qt早期版本,组件中包含了相应的item,例如QTableWidget中包含有QTableWidgetItem等。但是对于很大的数据,我们则需要使用Qt的view类,比如QListView,QTabelView和QTreeView,同时需要提供一个model,可以是自定义model,也可以是Qt预置的model。例如,如果数据来自数据库,那么你可以使用QTabelView和QSqlTableModel这两个类。