简介
在公司从事MFC的程序维护一年两个月,期间因为公司被QT告侵权对QT产生了抵触的心情。现在无奈要用到,需要抓紧学习了。
正文
1.数据模型
先说下刚用到的模型,模型也叫数据模型,也就是耳熟的MVC架构中的M(Model)。在QT中,数据模型被封装了几个经典的类:QFileSystemModel
、QStringListModel
、QStandardItemModel
等。
2.MVC架构
MVC架构的主要应用场景就是与用户有交互的程序。这个架构的好处就是把数据的展示
和数据本身
解耦,与用户交互的前端需要更新时只需要改改前端的代码和少量数据模型相关的代码,从而使程序更新升级更快且稳定。
3.MVC架构与数据模型的关系
下面这幅图是MVC的一种简单模式,从图中要清楚,数据模型是数据库数据的一份 摘要 ,视图负责把摘要显示出来。
4.如果让你设计M-V,你如何实现(面试问)?
答:我把QT的实现分析下,比如说我的数据库存的是一张公司职工个人信息表,要开发一款显示全体职工的基本信息的程序。那我会设计一个结构体存储个人的基本信息,再用链表存储所有员工的信息。视图部分访问数据模型对外提供的获取链表对象的接口进行数据获取与显示。代码大致如下:
/***极简版本***/
// 数据模型
typedef struct {
string name;
int age;
} Info;
list<Info*> infoDataModel;
// 视图部分
list<Info*> plist = infoDataModel;
while(plist .begin())
{
show(plist->name,plist->age);
plist=plist->next;
}
注意到上面的代码视图部分是需要知道模型部分定义的数据结构的,所以还是具有一定耦合。
5.上面的代码只完成了单向的显示,视图更新数据到数据模型如何实现?
答:这部分的功能实现主要划分到控制器(Controler),控制器接收用户的更改,传递到数据模型部分,由数据模型更新数据库。控制器的实现,底层是消息机制,比如用户点击编辑框进行修改数据,会触发一个“消息”
,控制器接收到这个消息再获取更新后的具体数值,紧接着进行“消息”
的派发。
因为控制器要把标准的用户更改数值消息传递到数据模型,用户的消息基本是有限的,但是对应的数据模型实际上是千差万别的,那么控制器是如何知道用户修改的值应该对应到数据模型的哪一个呢?总不能建立一对一的强关联吧?
这里我的思路是消息体里面要存上数据模型对应的变量ID,刚刚那个简单的代码,我需要在里面加上ID这个变量,以方便确定用户更新的是哪个变量。
typedef struct {
string name;
int age;
longlong id;
} Info;
很明显变量的id是公共的,我可以把id抽象到一个父类,这样框架访问的只有父类的id,如果你要用这个框架进行数据的更新,就必须继承我设计好的父类。代码大体是这样:
class DataObject
{
public:
getId(){return id;}
private:
longlong id;
}
class EmployeeInfo : public DataObject
{
string name;
int age;
} ;
6.你的设计有啥不足的地方(面试问)?
答:上面只是按照mvc的思想进行的个人设计,考虑不周的地方很多,比如:多线程下,如果用户通过视图修改数据的时候,视图也同时从数据模型获取数据,存在回写的bug,比如模型里面张三是22,我通过视图更新为23,由于多线程,写数据还没到模型,视图从模型再刷新数据,就会把旧值22再读到视图中显示出来。22 -> 23 -> 22
QT的数据模型与视图结构的用法
简单的字符串链表为数据模型的实现。
//1.数据“源”对象
QStringList theStrList; //保存初始 StringList
theStrList<<"新"<<"春"<<"快"<<"乐"<<"2023"; //初始化 StringList
//2.包装成数据模型
theModel=new QStringListModel(this); //创建数据模型
theModel->setStringList(theStrList); //为模型设置StringList,会导入StringList的内容
//3.将数据模型与视图关联
ui->listView->setModel(theModel); //为listView设置数据模型