视图项模型:如果是listModel,可以继承QAbstractListModel
QAbstractListModel
提供了一个抽象模型,可以对其进行子类化以创建一维列表模型。
QAbstractListModel 为模型提供了一个标准接口,将它们的数据表示为一个简单的非分层项目序列。它不能直接使用,但必须是子类。
由于模型提供了比 QAbstractItemModel 更专业的接口,因此不适合与树视图一起使用;如果要为此目的提供模型,则需要将 QAbstractItemModel 子类化。如果您需要使用多个列表模型来管理数据,则将 QAbstractTableModel 子类化可能更合适。
可以通过子类化此类并实现所需的最少功能来创建简单的模型。例如,我们可以实现一个简单的基于 QStringList 的只读模型,它为 QListView 小部件提供字符串列表。在这种情况下,我们只需要实现 rowCount() 函数返回列表中的项目数,并实现 data() 函数从列表中检索项目。
由于模型表示一维结构,因此 rowCount() 函数返回模型中的项目总数。 columnCount() 函数实现了与各种视图的互操作性,但默认情况下通知视图模型仅包含一列。
在继承 QAbstractListModel 时,您必须提供 rowCount() 和 data() 函数的实现。表现良好的模型还提供了 headerData() 实现。
如果您的模型在 QML 中使用并且需要 roleNames() 函数提供的默认角色以外的角色,则必须覆盖它。
对于可编辑列表模型,您还必须提供 setData() 的实现,并实现 flags() 函数,以便它返回一个包含 Qt::ItemIsEditable 的值。
请注意,QAbstractListModel 提供了 columnCount() 的默认实现,它通知视图此模型中只有一列项目。
为可调整大小的类列表数据结构提供接口的模型可以提供 insertRows() 和 removeRows() 的实现。在实现这些函数时,调用适当的函数很重要,以便所有连接的视图都知道任何更改:
insertRows() 实现必须在将新行插入数据结构之前调用 beginInsertRows(),之后必须立即调用 endInsertRows()。
removeRows() 实现必须在从数据结构中删除行之前调用 beginRemoveRows(),并且之后必须立即调用 endRemoveRows()。
注意:模型子类化参考中提供了一些用于子类化模型的一般准则。
另请参阅模型类、模型子类化参考、QAbstractItemView、QAbstractTableModel 和项目视图拼图示例。
自定义model
如下展示数据:
其中main.qml:
自定义了一个TestModel:
"testmodel.h"
#ifndef TESTMODEL_H
#define TESTMODEL_H
#include <QObject>
#include <QAbstractListModel>
#include <QQmlListProperty>
class TestListItem:public QObject{
Q_OBJECT
Q_PROPERTY(QString name WRITE setName READ getName NOTIFY nameChanged)
Q_PROPERTY(int value WRITE setValue READ getValue NOTIFY valueChanged)
public:
using QObject::QObject;
void setName(const QString &name);
QString getName()const ;
void setValue(int value);
int getValue() const;
~TestListItem();
signals:
void nameChanged();
void valueChanged();
private:
QString _name;
qint32 _value;
};
class TestModel:public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<TestListItem> datas READ datas NOTIFY datasChanged)
enum Role{
Name = Qt::DisplayRole + 1,
Value
};
signals:
void datasChanged();
public:
using QAbstractListModel::QAbstractListModel;
using TestItemListType = QList<TestListItem *>;
TestModel();
Q_INVOKABLE void append(const QJsonObject &item) ;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QQmlListProperty<TestListItem> datas();
static void AppendFunction(QQmlListProperty<TestListItem> *,TestListItem *);
static int CountFunction(QQmlListProperty<TestListItem> *);
static TestListItem * AtFunction(QQmlListProperty<TestListItem> *,int);
static void ClearFunction(QQmlListProperty<TestListItem> *);
private:
mutable QHash<int, QByteArray> _roles;
QList<TestListItem *> _items;
};
#endif // TESTMODEL_H
"testmodel.cpp"
#include "testmodel.h"
#include <QJsonObject>
#include <QDebug>
void TestListItem::setName(const QString &name){
if (_name != name){
_name = name;
emit nameChanged();
}
}
QString TestListItem::getName()const {
return _name;
}
void TestListItem::setValue(int value){
if (_value != value){
_value = value;
emit valueChanged();
}
}
int TestListItem::getValue() const{
return _value;
}
TestListItem::~TestListItem(){
qDebug() << "TestModel::~TestModel";
}
TestModel::TestModel()
{
qDebug() << "TestModel::TestModel";
}
void TestModel::append(const QJsonObject &item){
qDebug() << "TestModel::append";
auto tmp = new TestListItem(this);
if (!tmp){
return;
}
tmp->setName(item.value("name").toString());
tmp->setValue(item.value("value").toInt());
_items.append(tmp);
endResetModel();
}
/*
对应delegate:Text{
text:name + " " + value
}中的 name value
*/
QHash<int, QByteArray> TestModel::roleNames() const {
if (_roles.isEmpty()){
_roles.insert(Role::Name,"name");
_roles.insert(Role::Value,"value");
}
return _roles;
}
QVariant TestModel::data(const QModelIndex &index, int role) const {
qDebug() << "TestModel::data ";
if (!index.isValid()){
return QVariant();
}
if (role == Role::Name){
return QVariant(_items[index.row()]->getName());
}
else if (role == Role::Value){
return QVariant(_items[index.row()]->getValue());
}
return QVariant();
}
int TestModel::rowCount(const QModelIndex &parent) const {
return _items.count();
}
QQmlListProperty<TestListItem> TestModel::datas(){
qDebug() << "TestModel::datas ";
return QQmlListProperty<TestListItem>(this,&_items,
&TestModel::AppendFunction,
&TestModel::CountFunction,
&TestModel::AtFunction,
&TestModel::ClearFunction);
}
void TestModel::AppendFunction(QQmlListProperty<TestListItem> *items,TestListItem *item){
qDebug() << "TestModel::AppendFunction ";
static_cast<TestItemListType*>(items->data)->append(item);
}
int TestModel::CountFunction(QQmlListProperty<TestListItem> *items){
return static_cast<TestItemListType*>(items->data)->count();
}
TestListItem * TestModel::AtFunction(QQmlListProperty<TestListItem> *items,int index){
return static_cast<TestItemListType*>(items->data)->at(index);
}
void TestModel::ClearFunction(QQmlListProperty<TestListItem> *items){
static_cast<TestItemListType*>(items->data)->clear();
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "testmodel.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);
qmlRegisterType<TestListItem>("TestModule",1,0,"TestListItem");
qmlRegisterType<TestModel>("TestModule",1,0,"TestModel");
QQmlApplicationEngine engine;
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();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import TestModule 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ListView{
anchors.fill: parent
model:TestModel{
id:testmodel
datas: [
TestListItem{
name: "zhangsan"
value: 123
},
TestListItem{
name: "zhangsan1"
value: 1234
}
]
}
delegate: Text{
text:name + " " + value
MouseArea{
anchors.fill: parent
onClicked: {
testmodel.append({name:"qml",value:123})
}
}
}
}
}