二十六、模型、视图、代理
模型(Model)
InterView框架中所有模型都基于抽象基类QAbstractItemModel类,此类由QAbstractListModel、QAbstractTableModel和QAbstractProxyModel类继承。
视图(View)
InterView框架中的所有视图都是基于抽象基类QAbstractItemView类,此类由QColumnView、QHeaderView、QListView、QTableView和QTreeView继承。
代理(Delegate)
InterView 框 架 中 的 所 有 代 理 都 基 于 抽 象 基 类QAbstractItemDelegate类,此类由QItemDelegate和QStyledItemDelegate类继承
这里我们只做一些模型和视图的项目,代理的项目就不做了
首先看模型的项目
实现以下功能
首先我们随便创建一个工程,因为接下来我们自己创建一个类,并且在main函数中使用,我们把类名取名为“ModelExtended”。
首先看modelextended.h
#ifndef MODELEXTENDED_H
#define MODELEXTENDED_H
#include<QAbstractTableModel>
#include<QVector>
#include<QMap>
#include<QStringList>
class ModelExtended : public QAbstractTableModel
{
Q_OBJECT
public:
explicit ModelExtended(QObject *parent=0);
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const; //行
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const; //列
QVariant data(const QModelIndex &index,int role) const; //显示数据
QVariant headerData(int section,Qt::Orientation orientation,int role) const; //设置表头
private:
QVector<short> empIndex;
QVector<short> empNameIndex;
QMap<short,QString> empNo;
QMap<short,QString> empName;
QStringList viewListTitle;
QStringList empDepartment;
void modelFunc();
};
#endif // MODELEXTENDED_H
int QAbstractItemModel::rowCount(const QModelIndex &parent = QModelIndex()) const:
返回给定父项下的行数。当父元素有效时,意味着rowCount返回父元素的子元素个数。
注意:当实现基于表的模型时,当父元素有效时,rowCount()应该返回0。
注意:这个函数可以通过元对象系统从QML调用。看到Q_INVOKABLE。
int QAbstractItemModel::columnCount(const QModelIndex &parent = QModelIndex()) const:
返回给定父元素的子元素的列数。
在大多数子类中,列的数量与父类无关。
QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const:
为索引引用的项返回存储在给定角色下的数据。
注意:如果没有要返回的值,则返回无效的QVariant,而不是返回0。
注意:这个函数可以通过元对象系统从QML调用。看到Q_INVOKABLE。
QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const:
以指定方向返回头部中给定角色和部分的数据。
对于水平标头,区段号对应于列号。类似地,对于垂直标头,节号对应于行号。
注意:这个函数可以通过元对象系统从QML调用。看到Q_INVOKABLE。
modelextended.cpp
#include "modelextended.h"
ModelExtended::ModelExtended(QObject *parent) :
QAbstractTableModel(parent)
{
empNo[1]="112233";
empNo[2]="445566";
empNo[3]="778899";
empName[1]="zhangsan";
empName[2]="lisi";
empName[3]="wangwu";
modelFunc();
}
void ModelExtended::modelFunc()
{
viewListTitle<<"员工编号"<<"员工姓名"<<"员工部门";
empIndex<<1<<2<<3;
empNameIndex<<1<<2<<3;
empDepartment<<"营销部"<<"财务部"<<"研发部";
}
int ModelExtended::rowCount(const QModelIndex &parent) const
{
return empIndex.size();
}
int ModelExtended::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant ModelExtended::data(const QModelIndex &index, int role) const
{
if(!index.isValid()) return QVariant();
if(role==Qt::DisplayRole)
{
switch (index.column())
{
case 0:
return empNo[empIndex[index.row()]];
break;
case 1:
return empName[empNameIndex[index.row()]];
break;
case 2:
return empDepartment[index.row()];
break;
default:
return QVariant();
break;
}
}
return QVariant();
}
QVariant ModelExtended::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role==Qt::DisplayRole && orientation==Qt::Horizontal)
return viewListTitle[section];
return QAbstractTableModel::headerData(section,orientation,role);
}
这段代码是一个继承自QAbstractTableModel的自定义Model,用于在视图中显示员工的编号、姓名和部门。其中,modelFunc()函数用于初始化一些数据,rowCount()函数返回员工数量,columnCount()函数返回3列,data()函数用于返回每个单元格的数据,headerData()函数用于返回表头数据。具体实现细节可以参考代码注释。
DisplayRole
int QModelIndex::column() const:
返回此模型索引所引用的列
一下实现视图功能
直接在main函数里实现
#include "mainwindow.h"
#include <QApplication>
#include<QAbstractItemView>
#include<QAbstractItemModel>
#include<QItemSelectionModel>
#include<QSplitter>
#include<QDirModel>
#include<QTreeView>
#include<QListView>
#include<QTableView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// MainWindow w;
// w.show();
QDirModel model;
QTreeView tree;
QListView list;
QTableView table;
tree.setModel(&model);
list.setModel(&model);
table.setModel(&model);
QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,SLOT(setRootIndex(QModelIndex)));
QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table,SLOT(setRootIndex(QModelIndex)));
QSplitter *qsp=new QSplitter;
qsp->addWidget(&tree);
qsp->addWidget(&list);
qsp->addWidget(&table);
qsp->show();
return a.exec();
}
这段代码主要是使用Qt框架实现了一个简单的文件浏览器。具体实现过程如下:
1. 引入必要的头文件。
2. 实例化QApplication对象。
3. 实例化QDirModel对象,该对象提供了一个文件系统模型,可以用于显示文件系统的目录结构。
4. 实例化QTreeView、QListView、QTableView对象,分别用于以树形结构、列表结构、表格结构显示文件系统的目录结构。
5. 将QDirModel对象设置为QTreeView、QListView、QTableView的模型。
6. 通过QObject::connect()函数将QTreeView的doubleClicked()信号与QListView和QTableView的setRootIndex()槽函数连接起来,实现双击QTreeView中的目录项时,QListView和QTableView同时显示该目录下的文件和子目录。
7. 实例化QSplitter对象,将QTreeView、QListView、QTableView添加到QSplitter中,实现三个视图的分割显示。
8. 显示QSplitter。
void QAbstractItemView::doubleClicked(const QModelIndex &index):
该信号在双击鼠标按钮时发出。鼠标双击的项由index指定。该信号仅在索引有效时发出。
void QAbstractItemView::setRootIndex(const QModelIndex &index):
将根项设置为给定索引处的项。