引言
Qt的模型视图结构分为三部分,模型(model)、视图(view)、代理(Delegate)。其中,模型与数据源通信,并为其他不见提供接口;而视图从模型中获得用来引用数据条目的模型索引(Model Index)。在视图中,代理负责绘制绘制数据条目,当编辑条目时,代理和模型直接进行通信。模型/视图/代理之间通过信号和槽进行通信。它们之间的关系如下:
- 数据发生变化时,模型发出信号通知视图。
- 用户对界面进行操作,视图发出信号。
- 代理发出信号告知模型和视图编辑器目前的状态。
模型(model)
InterView框架中的所有模型都基于抽象基类QAbstractItemModel类,此类由QProxyModel、QAbstractListModel、QAbstracTableModel、QAbstracProxyModel、QDirModel、QFileSystemModel、QHelpContentModel和QStandardItemModel类继承。其中,QAbstractListModel类和QAbstracTableModel类是列表和表格模型的抽象基类,如果需要实现列表和表格模型,则应从这两个类继承。完成QStringList存储的QStringListModel继承自QAbstractListModel类,而与数据库有关的QSqlQueryModel类继承自QAbstracTableModel类;QAbstracProxyModel类是代理模型的抽象类;QDirModel类是文件和目录的存储模型。
视图
InterView框架中所有的视图都是基于抽象类QAbstractItemView类,此类由QColumnView、QHeaderView、QListView、QTableView、和QTreeView类继承。QListView类由QUndoView和QListWidget类继承;QTableView由QTableWidget类继承;QTreeView类由QTreeWidget类继承。而QListWidget类、QTableWidget类、QTreeWidget类实际上已经包含了数据,是模型/视图集成在一起的类。
代理
InterView框架中所有的代理类都基于抽象基类QAbstractItemDelegate类,此类由QItemDelegate和QSyledItemDelegate类继承。其中,QItemDelegate类由表示数据库中关系代理的QSqlRelationDelegate类继承。
代码示例:实现一个文件目录浏览器
```cpp
#include <QtWidgets/QApplication>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QDirModel>
#include <QListView>
#include <QTableView>
#include <QTreeView>
#include <QSplitter>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDirModel model;
QTreeView tree;
QListView list;
QTableView table;
// 设置View对象的model
tree.setModel(&model);
list.setModel(&model);
table.setModel(&model);
// 设置QTreeView对象的选择方式为多选
tree.setSelectionMode(QAbstractItemView::MultiSelection);
// 设置QListView和QTableView使用QTreeView对象相同的选择模型
list.setSelectionModel(tree.selectionModel());
table.setSelectionModel(tree.selectionModel());
QObject::connect(&tree, SIGNAL(doubleClicked(QModelIndex)), &list, SLOT(setRootIndex(QModelIndex)));
QObject::connect(&tree, SIGNAL(doubleClicked(QModelIndex)), &table, SLOT(setRootIndex(QModelIndex)));
QSplitter* splitter = new QSplitter;
splitter->addWidget(&tree);
splitter->addWidget(&list);
splitter->addWidget(&table);
splitter->setWindowTitle(QObject::tr("Model/view"));
splitter->show();
return a.exec();
}