虽然QML已经提供了几种比较常见的模型,但是依然不足以应对应用中可能出现的情况。
所以才需要自定义c++模型,然后可以在QML中使用,这有助于将c++数据模型或其他复杂的数据集暴露给QML。
C++模型类可以是QStringList、QObjectList或者QAbstractItemModel ,前面两个对于暴露简单数据集是非常有用的,而QAbstractItemModel则为更复杂的模型提供了灵活的解决方案。
本章使用QAbstractItemModel自定义模型,其他有兴趣的可以自行了解。
话不多说,直接上代码 (ps:自己做的小demo)
// !!!!!StudentModel.h
#include <QAbstractListModel>
#include <QJsonObject>
#include <QJsonArray>
//子类化QAbstractListModel
class StudentModel : public QAbstractListModel{
Q_OBJECT
public:
enum Student_Role{ //定义数据的角色
IdRole = Qt::UserRole+1, //UserRole表示合法位置的起始位置
NameRole,
SexRole,
AgeRole,
SchoolRole,
StuNumberRole
};
Q_ENUM(Student_Role) //必须有这一句,使枚举类可以使用
explicit StudentModel(QObject *parent = nullptr);
~StudentModel();
//必须重写的三个方法
//第一个方法返回数据条目数
//第二个方法返回指定角色的数据
//第三个方法返回数据与角色的映射关系
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
protected:
QHash<int, QByteArray> roleNames() const override;
public slots:
//对数据的基本 *** 作
void setStudent(const QJsonArray StudentJsonArray); //初始化数据
void insertStudent(const QJsonObject &StudentJsonobject,int &index); //添加数据
void removeStudent(int &index); //移除数据
private:
//以下是数据源
QList<int> m_idList;
QList<QString> m_nameList;
QList<QString> m_sexList;
QList<int> m_ageList;
QList<QString> m_schoolList;
QList<QString> m_schoolNumberList;
};
// !!!!!StudentModel.cpp
#include "StudentModel.h"
#include <QDebug>
StudentModel::StudentModel(QObject *parent)
:QAbstractListModel(parent)
{
}
StudentModel::~StudentModel()
{
}
int StudentModel::rowCount(const QModelIndex &parent) const{
return m_idList.size();
}
QVariant StudentModel::data(const QModelIndex &index, int role) const{
if(!index.isValid()){
return QVariant();
}
switch (role) {
case IdRole:
return m_idList.at(index.row());
case NameRole:
return m_nameList.at(index.row());
case SexRole:
return m_sexList.at(index.row());
case AgeRole:
return m_ageList.at(index.row());
case SchoolRole:
return m_schoolList.at(index.row());
case StuNumberRole:
return m_schoolNumberList.at(index.row());
default:
return QVariant();
}
}
QHash<int, QByteArray> StudentModel::roleNames() const{
static QHash<int, QByteArray> roles{
{IdRole,"id"},
{NameRole,"name"},
{SexRole,"sex"},
{AgeRole,"age" },
{SchoolRole,"school"},
{StuNumberRole,"stuNo" }
};
return roles;
}
//注入初始数据
void StudentModel::setStudent(const QJsonArray StudentJsonArray){
beginResetModel(); //重置数据必须遵循的规则,表示开始
m_idList.clear();
m_nameList.clear();
m_sexList.clear();
m_ageList.clear();
m_schoolList.clear();
m_schoolNumberList.clear();
for(int i=0;i<StudentJsonArray.size();i++){
QJsonObject obj = StudentJsonArray.at(i).toObject();
m_idList << obj["id"].toInt();
m_nameList << obj["name"].toString();
m_sexList << obj["sex"].toString();
m_ageList << obj["age"].toInt();
m_schoolList << obj["school"].toString();
m_schoolNumberList << obj["stuNo"].toString();
}
endResetModel(); //重置数据必须遵循的规则,表示结束
}
//增加数据
void StudentModel::insertStudent(const QJsonObject &StudentJsonobject,int &index){
if(index <0 || index > rowCount()) //无效处理
return;
int id = StudentJsonobject.value(QLatin1String("id")).toInt();
QString name = StudentJsonobject.value(QLatin1String("name")).toString();
QString sex = StudentJsonobject.value(QLatin1String("sex")).toString();
int age = StudentJsonobject.value(QLatin1String("age")).toInt();
QString school = StudentJsonobject.value(QLatin1String("school")).toString();
QString stuNo = StudentJsonobject.value(QLatin1String("stuNo")).toString();
//插入数据需遵循的规则,表示开始
beginInsertRows(QModelIndex(),index,index); //第一个参数表示在顶级根(由于是列表结构所以表示当前列表的根),第二个参数表示起始位置,第三个参数表示结束位置,由于只有一列,所以两者都一样
m_idList.insert(index,id);
m_nameList.insert(index,name);
m_sexList.insert(index,sex);
m_ageList.insert(index,age);
m_schoolList.insert(index,school);
m_schoolNumberList.insert(index,stuNo);
endInsertRows(); //插入数据需遵循的规则,表示结束
}
//移除数据
void StudentModel::removeStudent(int &index){
if(index < 0 || index > rowCount())return;
beginRemoveRows(QModelIndex(),index,index); //移除数据需遵循的规则,表示开始
m_idList.removeAt(index);
m_nameList.removeAt(index);
m_sexList.removeAt(index);
m_ageList.removeAt(index);
m_schoolList.removeAt(index);
m_schoolNumberList.removeAt(index);
endRemoveRows(); //移除数据需遵循的规则,表示结束
}
// !!!!!main.cpp
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQmlContext>
#include <QGuiApplication>
#include "StudentModel.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc,argv);
QQmlApplicationEngine engine;
StudentModel model;
//下面两种方法均可
//第一种是直接在上下文环境直接注册进去一个实例
//第二种将模型类注册进去,以至于模型类可以像QML组件一样实例化
engine.rootContext()->setContextProperty("$Model",&model); //注入模型
// qmlRegisterType("Com.Lc.Classes", 1, 0, "StudentModel");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
至此,c++自定义模型结束了,可以在QML进行使用了。
是不是都是套路?
简单总结一下实现c++自定义模型的步骤:
- 第一步:子类化QAbstractItemModel。
重写它的三个方法。
- 第二步:定义角色枚举,并使用Q_ENUM()方法
- 第三步:定义数据源
- 第四步:根据角色定义和数据源,重新实现它的三个方法
- 第五步(可选):如有需要增删改查 *** 作,需遵循它的规则!!!
- 第六步:在QML中注册c++模型类
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)