作为Qt的业余使用人员,对Qt一直一知半解;最近做个小玩意,要显示一个类似微信好友列表的东东,才发现对mode/view框架完全不懂,在此对MCV模型做一次全面学习,以此记录!
学习实例来源与Qt自带的例子,目录:Qt5.9.0\Examples\Qt-5.9\widgets\tutorials\modelview。
=============================================================================================
标准控件QListWidget、QTreeWidget、QTableWidget,直接存储文本信息等内容(如其他Qt自带标准控件),数据是通过QStandarditem类型一项项添加上去的
mod/view模型,实现显示和数据的分离:
这样的好处是用mode来组织数据(其实mode也不存储数据),不同的view都可以展示数据,而且数据是一致的,即只要改变数据,所有的view会自动更新。
数据可以是通过各种方式提供的,是底层的;mode对底层数据进行了封装,各种view直接调用mode即可实现数据的显示。
mode的基类是QAbstractItemModel,Qt已经实现了一些类:
QStringListModel 用于存储简单的QString项目列表。
QStandardItemModel管理更复杂的树型结构数据项,每项都可以包含任意数据。
QFileSystemModel提供本地文件系统中的文件与目录信息。
QSqlQueryModel、QSqlTableModel、QSqlRelationTableModel用来访问数据库。
但是更多的情况,我们需要继承基类,自定义我们自己的类。
程序目录结构如下:
mymodel.h
#include
class MyModel : public QAbstractTableModel
{
Q_OBJECT
public:
MyModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const override ;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};
继承QAbstractTableModel基类,只需实现这三个纯虚函数:
int rowCount(const QModelIndex &parent = QModelIndex()) const override ;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
mymode.cpp实现这三个方法:
#include "mymodel.h"
MyModel::MyModel(QObject *parent)
:QAbstractTableModel(parent)
{
}
int MyModel::rowCount(const QModelIndex & /*parent*/) const
{
return 2;
}
int MyModel::columnCount(const QModelIndex & /*parent*/) const
{
return 3;
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
return QString("Row%1, Column%2")
.arg(index.row() + 1)
.arg(index.column() +1);
}
return QVariant();
}
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView tableView;
MyModel myModel(0);
tableView.setModel( &myModel );
tableView.show();
return a.exec();
}
main函数定义一个QTableView,只需setMode设置mode即可,mode就是我们自定的mymode。
mymode中的rowCount()告诉view有几行,columnCount()告诉view有几列,data()告诉view要显示的数据!这些都是MV框架自动做的,我们只需要实现这几个函数就行.
运行结果:
其中最重要的就是实现data()函数。
每个单元格都会调用data()获取内容,本例6个单元格,但实际上每个单元格都调用了7次data(),为何会调用7次?是因为data()的参数role有7个取值,本例只是显示,是用的Qt::DisplayRole.
关于role:
view中数据格式用mode的角色进行控制,角色是枚举型的enum Qt::ItemDataRole,其中mode使用其中的7中角色(这也是为何每个单元格要调用7次data(),每次调用都是对单元格进行相应的控制),分别是枚举enum Qt::ItemDataRole中的:6、7、9、10、1、0、8
Qt::FontRole 字体
Qt::TextAlignmentRole 对其方式
Qt::ForegroundRole/Qt::TextColorRole 字体颜色
Qt::CheckStateRole 复选框是否选择
Qt::DecorationRole 图像
Qt::DisplayRole 显示
Qt::BackgroundRole/Qt::BackgroundColorRole 背景
具体含义及用法,希望后续会涉及!
第二章会介绍其中几个的用法事例!