QStandardItemModel是一个通用的模型类:
1、能够以任意的方式组织数据(线性、非线性);
2、数据组织的基本单位为数据项(QStandardItem);
3、每一个数据项能够存储多个数据状态(附加数据角色);
4、每一个数据项能够对数据状态进行控制(可编辑,可选。。。)。
组织结构如下:
新类型引入:QVariant:
1、QVariant 是一个用于封装的类型;
2、QVariant 能够表示大多数常见的值类型;
3、QVariant 每次只能封装(保存)单一类型的值;
4、QVariant 意义在于能够设计“返回类型可变的函数”。
应用实例如下:
#include <QCoreApplication>
#include <QVariant>
#include <QPoint>
#include <QDebug>
QVariant func() //返回值的类型此处是不确定的
{
QVariant ret;
return ret;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVariant v1(1);
QVariant v2(3.14);
QVariant v3("520");
QVariant v4(QPoint(10, 10));
QVariant v5;
qDebug() << v1.type();
qDebug() << v1.typeName();
qDebug() << v1.toInt();
qDebug() << v1.value<int>();
qDebug() << endl;
qDebug() << v2.type();
qDebug() << v2.typeName();
qDebug() << v2.toInt();
qDebug() << v2.toDouble();
qDebug() << v2.value<int>();
qDebug() << endl;
qDebug() << v3.type();
qDebug() << v3.typeName();
qDebug() << v3.toInt();
qDebug() << v3.value<int>();
qDebug() << v3.value<QString>();
qDebug() << endl;
bool ok = true;
qDebug() << v4.type();
qDebug() << v4.typeName();
qDebug() << v4.toInt(&ok);
qDebug() << ok;
qDebug() << v4.toPoint();
qDebug() << endl;
qDebug() << v5.isValid();
return a.exec();
}
运行结果:
注:在对QVariant类型的数据进行操作时,应首先检查其是否可用。(IsValid()函数)
工程中常用的模型设计:
1、解析数据源中的数据(数据库,网络,串口,等);
2、将解析后的数据存入QStandardItem对象中;
3、根据数据间的关系在QStandardItemModel对象中组织数据项;
4、选择合适的视图显示数据项。
实例分析:
分析思路如下:
系统架构图:
工程中常用的数据应用架构分为4层:
数据层,数据表示层,数据组织层,数据显示层。
系统核心类图:
具体实现:
将每个功能层做成一个相对应的类,从而根据具体类实现相应的功能。
1、DataSource类的设计与实现:
设置数据源并读取数据;对数据进行解析后生成数据对象。
.h文件如下:
#include <QObject>
#include <QList>
#include "ScoreInfo.h"
class DataSource : public QObject
{
Q_OBJECT
QList<ScoreInfo> m_data; //创建ScoreInfo类型的一个QList对象
bool parse(QString line, ScoreInfo& info);
public:
explicit DataSource(QObject* parent = 0);
bool setDataPath(QString path);
QList<ScoreInfo> fetchData();
int count();
};
2、ScoreInfo类的设计与实现:
封装数据源中的一组完整数据;提供返回具体数据值的接口函数。
.h文件如下:
#include <QObject>
#include <QString>
class ScoreInfo : public QObject
{
Q_OBJECT
QString m_id;
QString m_name;
int m_score;
public:
explicit ScoreInfo(QObject *parent = 0);
explicit ScoreInfo(QString id, QString name, int score);
ScoreInfo(const ScoreInfo& obj);
ScoreInfo& operator =(const ScoreInfo& obj);
QString id();
QString name();
int score();
};
3、ScoreInfoModel类的设计与实现:
使用标准模型类QStandardItemModel作为成员;以ScoreInfo类对象为最小单位进行数据组织。
.h文件如下:
#include <QObject>
#include <QStandardItem>
#include <QTableView>
#include "ScoreInfo.h"
class ScoreInfoModel : public QObject
{
Q_OBJECT
QStandardItemModel m_model;
public:
explicit ScoreInfoModel(QObject* parent = 0);
bool add(ScoreInfo info);
bool remove(int i);
ScoreInfo getItem(int i);
int count();
void setView(QTableView& view);
signals:
public slots:
};
问题1:为什么DataScoure类中获取数据的方式是fetchData,而不是getData?
答:我们来看fetchData()的具体实现:
QList<ScoreInfo> DataSource::fetchData()
{
QList<ScoreInfo> ret = m_data;
m_data.clear();
return ret;
}
函数实现过程中,对取到的数据进行复制,并且将取到的数据删除,避免了数据的冗余。
问题2:这样架构一个数据应用程序有什么好处?
答:当数据源或者视图需要发生变化的时候,可以最小程度的减少代码改动,将改动可以具体到每一次。