深入理解QT模型/视图编程(一)

发布时间 2023-07-30 16:36:41作者: 疾速瓜牛

关于MVC模式

说到这个,还是离不开MVC模式,model是数据的抽象,view是视图的抽象,controller是交互的抽象;之前有一篇文章简单介绍过一个MVC的例子;其中的关系大致可以用下面这段伪代码来了解:

model.setDataSource(xxx); //从xxx处拿到数据
view1.setModel(&model); //为视图指定模型,view注册成为model的观察者
view1.show(); //View类由用户自己定制
view2.setModel(&model); //为视图指定模型
view2.show(); //同一个模型具有不同的视图
//最后,控制器更改模型数据,实际是model提供对datasource的操作接口
// model的update_datasource方法最后会通知作为观察者的view,数据源发生改变,调用view之前注册的onNotify方法;
controller.setdata(model);

MVC的关系可以用下图表示:

在这个图中,View是前端,负责向用户展示数据,同时,也可以提供交互逻辑,可以修改某些数据,最终想要达到修改的源数据的操作则需要借助controller操作model的接口,对DataSource进行更新,更新之后同时notify它的观察者,也就是最终View也需要Update自己的视图;

 

关于模型

这里注意,数据本身并不是存储在model中,数据源可以是数据库,文件,或者一个类,一个结构体等;只是说模型类型为数据的操作提供接口,方便我们的使用;QT中所有的模型都基于QAbstractItemModel类,然后为一些常用的视图提供了相应的模型,比如:QStringListModel 用于存储简单的QStringList列表,提供了如下接口用于快速操作QStringList数据源:

 QStandardItemModel 用于管理复杂的树形结构数据,每一个数据项可以包含任意的数据;如果QT提供的这些标准模型无法满足需要,还可以子类化QAbstracItemModel 等基类创建自定义的模型;

关于视图

QListView将数据显示为一个列表,QTableView将模型显示在一个表格中,QTreeView将模型的数据项显示在具有层次的列表中;这些类都是基于QAbstractItemView抽象基类,也可以将其子类化来提供定制的视图;

关于委托

委托也被称为代理,可以通过委托定制数据的渲染和编辑方式;注意QT里面没有控制器的概念,而是采用了委托Delegate的概念来达到控制器的效果;委托和控制器的不同之处在于,委托除了可以Cover控制器的角色外,还可以对要渲染的item进行定制,也就是一旦我们为View指定了Delegate并重载了其paint方法,最终Model数据更改时,会触发signal,然后触发View的重绘,重绘的时候会调用Delegate的paint方法而不是默认的paint方法。这就是原先的item的默认paint委托给了DeleGate的paint,这就是委托的真正含义;大概就是下面这种关系;

 其中Delegate和View是相同的颜色,代表他们是一体的;原先模型直接到View的paint,由委托代劳;原先模型到model的修改也由委托代劳;

这就是QT为什么叫它Delegate的原因,因为它把模型和View解耦了;Model和View各自和Delegate打交道,这可不就是委托的字面意思嘛