1. Qt中的Model/View结构设计
其核心是界面组件与数据分离。Qt中分为如下几个核心概念:
-
数据(Data): 即实际的数据
-
视图组件(View): 即屏幕上的界面组件,用于给用户提供图形化界面操作窗口,使得用户可以查看,编辑,增删数据
-
数据模型(Model): 数据模型与数据直接通信,并为视图组件提供接口,让视图组件从中获取数据并显示在组件上,同样在视图组件上操作数据的结果也会通过数据模型对数据进行修改
-
代理(Delegate): 可以让用户指定数据界面显示和编辑方式
2. 视图组件
来看一下Qt中视图组件各类的继承图:
QColumnView: 用于多个QListView的树状层次显示,每一个节点都是一个QListView
QHeaderView: 提供行列表头的视图组件,比如QTableView
视图组件和数据模型通过setModel()建立关联,一个数据模型可以对应多个视图组件。也可以通过代理定制自己的视图组件
视图组件类是不会存储数据的,其通过setModel()来与数据模型进行关联,通过数据模型来操作数据,数据模型就相当于接口层。数据一般存储在数据库内。
这样就达到了数据与视图分离的目的。可以对大型数据源进行灵活操控
但反过来看QListWidget,QTableWidget以及QTreeWidget这3个类。其中都是通过Q*WidgetItem来存储数据,这就把数据与视图粘合在了一起。这只能对小型数据源进行操控。
3. 数据模型
数据模型提供数据访问的接口其不直接存储数据。数据可以存储在数据库,文件或者其他任何数据源内,来看一下数据模型类的结构图:
通过数据模型存取的每一个数据都有一个模型索引,视图组件和代理都通过模型索引来获取数据。
模型索引类QModelIndex为数据存储提供了一个临时指针,用于通过数据模型操作数据,由于数据模型内部结构可能发生改变,所以QModelIndex是临时的。
想要持久的需要QPersistentModelIndex类
实例化一个模型索引必须传入3个参数: 行号,列号和父项模型索引
假设父项是顶层节点,则总是用QModelIndex()来获取。
项的角色概念是数据模型中的一项可能在不同场景下有不同的数据。
通过:
void QStandardItem::setData(const QVariant &value, int role = Qt::UserRole + 1);
来设置项的角色以及对应的数据。
获取一个项中角色的数据可用:
QVariant QStandardItem::data(int role = Qt::UserRole + 1) const;
4. 代理
代理是视图组件上为编辑数据提供的编辑器。在表格组件上编辑数据时,默认使用的是QLineEdit组件代理。代理负责从数据模型中获取数据显示在视图组件上,然后用户在视图组件上修改后将结果存入数据模型内。
下面给出一个例子,这里通过QFileSystemModel来获取文件系统信息:
QFileSystemModel类需要通过setRootPath()来设置根目录
connect把选中的模型索引为信号分别传到listView和tableView中,代表根目录的改变
(完)