从MVC到Model-View-Delegate
Qt也写了不少时间了,来聊聊架构吧。
从java web中的mvc说起
做过Java Web开发的同学都知道,Java Web开发的发展历程。无模式->Model I ->Model II。
Model I
Model IModel II
Model II一个经典的MVC模式
MVCqml中的Model-View-Delegate
在Qt中,进行了些许变化
Qt QtController被Delegate换掉了。
在Java Web中,当一个请求发送到服务器时,服务器会对请求进行解析,选择相应的控制器(Controller),然后控制器调用相关的服务(Service),在服务中进行业务逻辑操作和数据库的增删改查(调用DAO层),然后控制器根据相应的结果选择合适的视图返回给浏览器。
在qml中又是如何做的呢?首先,数据和展示是分离的。Model负责提供数据,而View负责展示。如何展示的任务就落在委托(Delegate)身上了。
凡事都有Hello World
举一个例子——在qml中写一个列表。
模型怎么选?
qml中提供了不少模型
- ListModel
- XmlListModel
- VisualItemModel
- Integers as Models
- Object Instances as Models
- C++ Data Models
- ......
既然是做一个列表,当然可以用简单的ListModel。
ListModel{
ListElement{name:"a"}
ListElement{name:"b"}
ListElement{name:"c"}
}
视图怎么选?
qml中提供了三种基本的视图,分别是ListView,GridView,PathView。做列表,就选择ListView吧。
ListView{
model: xxxx
delegate: xxxx
}
怎么展示呢?也简单点吧,直接文本展示。
Text {text: name}
整个代码看起来是这个样子的
import QtQuick 2.9
ListView{
model: ListModel{
ListElement{name:"a"}
ListElement{name:"b"}
ListElement{name:"c"}
}
delegate: Text {text: name}
}
跑一跑
运行截图这样,我没有多写一行代码,一个使用Model-View-Delegate的qml小程序就跑出来了。当然,这离实际应用还差得比较远,但是跨出了第一步,后面可以慢慢来。好的开始是成功的一半。
当数据变复杂的时候,比如说我需要用json,只需要修改Model;当需要更加绚丽的效果的时候,比如说点击动画,只需要修改Delegate。
举一个复杂一点的例子
chat app chat app有没有感觉跟QQ不久前出的Tim很像,但是又不一样。
说几个点吧
- 联系人这里有一个标了数字的圈圈,有的有,有的没有
- 对话时对方的头像在左边,自己的在右边。聊天气泡颜色不一样
- 时间线(Timeline)这里最复杂,有的是好几张图片,有的有文字说明,还有的是视频
个人使用感受
Model-View-Delegate这么做也是为了方便解耦,当需求变了的时候,可以用小一些的代价去适应变化。
Model有不少冗余
习惯了json的我,qml的模型不能原生支持,实在是很痛苦啊。
给一个稍微复杂的例子,看看qml的模型是怎么写的
ListModel{
ListElement{
name:"a"
pics:[
ListElement{url:"a.png"},
ListElement{url:"b.png"}
]
}
...
}
是不是花了好的精力在ListElement上?用json又如何呢?
{
"list":[{
"name":"a",
"attrs":[{
"url":"a.png"
},{
"url":"b.png"
}]
}
]
}
是不是简洁了许多?是不是可以节省时间呢?用json去描述一个数据非常简单呢。
如何在项目中使用json呢?请参考这里
View有坑
视图中明确定义高度和宽度会有意向到不的错误哦!
没什么可说的Delegate
委托的话就跟自己写组件没什么区别。它相当于一个模板,等着模型的数据一来,就产生了非常漂亮的视图。
参考
- Qt5 Cadaques——Model-View-Delegate
- Models and Views in Qt Quick
- JSONListModel源码:GitHub