Person.h
#ifndef CPPACCESSQML_CALCULATOR_H
#define CPPACCESSQML_CALCULATOR_H
#include <QObject>
#include <QDebug>
#include "Student.h"
class Person : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(QList<Student*> students READ getStudents WRITE setStudents NOTIFY studentsChanged)
public:
explicit Person(QString name = "", int age = 0, QList<Student*> students = {}, QObject *parent = nullptr);
~Person() override;
QString getName() const { return m_name; }
void setName(const QString &name) { m_name = name; emit nameChanged(m_name); }
int getAge() { return m_age; }
void setAge(int age) { m_age = age; emit ageChanged(m_age); }
QList<Student*> getStudents() const { return m_students; }
void setStudents(const QList<Student*> &students) {
m_students = students;
emit studentsChanged();
}
Q_INVOKABLE void printName() { qDebug() << "name:" << m_name; }
private:
QString m_name;
int m_age;
QList<Student*> m_students;
signals:
void nameChanged(const QString &newName);
void ageChanged(int newAge);
void studentsChanged();
};
#endif
Person.cpp
#include "Person.h"
#include<QVariantMap>
#include<QVariantList>
Person::~Person() {}
Person::Person(QString name, int age, QList<Student*> students, QObject *parent): QObject(parent), m_name(name), m_age(age), m_students(students) {
}
Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include<QObject>
#include "Book.h"
class Student : public QObject
{
Q_OBJECT
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString level READ level WRITE setLevel NOTIFY levelChanged)
Q_PROPERTY(QList<Book*> books READ getBooks WRITE setBooks NOTIFY booksChanged)
public:
explicit Student(QObject *parent = nullptr);
explicit Student(int id, QString name, QString level, QList<Book*>);
int id() const { return m_id; }
void setId(int id) {
m_id = id;
emit idChanged();
}
QString name() const { return m_name; }
void setName(const QString &name) {
m_name = name;
emit nameChanged();
}
QString level() const { return m_level; }
void setLevel(const QString &level) {
m_level = level;
emit levelChanged();
}
QList<Book*> getBooks() const { return m_books; }
void setBooks(const QList<Book*> &books) {
m_books = books;
emit booksChanged();
}
signals:
void idChanged();
void nameChanged();
void levelChanged();
void booksChanged();
private:
int m_id;
QString m_name;
QString m_level;
QList<Book*> m_books;
};
#endif
Student.cpp
#include "Student.h"
Student::Student(QObject *parent) : QObject(parent), m_id(0), m_name(""), m_level("") {}
Student::Student(int id, QString name, QString level, QList<Book*> books): m_id(id), m_name(name), m_level(level), m_books(books) {
}
Book.h
#ifndef BOOK_H
#define BOOK_H
#include<QObject>
#include<QString>
class Book : public QObject
{
Q_OBJECT
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
public:
explicit Book(QString title, QObject *parent = nullptr);
QString title() const { return m_title; }
void setTitle(const QString &title) {
m_title = title;
emit titleChanged();
}
signals:
void titleChanged();
private:
QString m_title;
};
#endif
Book.cpp
#include "Book.h"
Book::Book(QString title, QObject *parent) : QObject(parent), m_title(title) {
}
MyListModel.h
#include<QAbstractListModel>
#include<QStringList>
#include<QQmlListProperty>
#include "Person.h"
class MyListModel : public QAbstractListModel {
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Person> persons READ getPersons)
public:
explicit MyListModel(QObject *parent = nullptr);
~MyListModel();
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void addPerson(const QVariantMap &data);
Q_INVOKABLE void updateData(int row, const QVariant &data, const QString &roleName);
QQmlListProperty<Person> getPersons() {
return QQmlListProperty<Person>(this, &m_persons);
}
private:
QList<Person*> m_persons;
enum Roles {
NameRole = Qt::UserRole + 1,
AgeRole,
StudentsListRole,
StudentsVariantListRole
};
};
MyListModel.cpp
#include "MyListModel.h"
MyListModel::MyListModel(QObject *parent) : QAbstractListModel(parent) {
m_persons.append(new Person("AA", 11, {
new Student(1, "1", "1", {
new Book("java11"),
new Book("java22"),
new Book("java33"),
}),
new Student(2, "2", "2", {
new Book("python11"),
new Book("python22"),
new Book("python33"),
})})
);
m_persons.append(new Person("BB", 22, {new Student(1, "11", "222", {}), new Student(2, "22", "8", {})}));
m_persons.append(new Person("CC", 33, {new Student(1, "111", "dd", {}), new Student(2, "222", "88", {})}));
m_persons.append(new Person("DD", 44, {new Student(1, "1111", "333", {}), new Student(2, "2222", "889", {})}));
}
MyListModel::~MyListModel() {}
int MyListModel::rowCount(const QModelIndex &parent) const {
if (parent.isValid()) {
return 0;
}
return m_persons.count();
}
QVariant MyListModel::data(const QModelIndex &index, int role) const {
if (!index.isValid() || index.row() >= m_persons.count()) {
return QVariant();
}
Person *person = m_persons.at(index.row());
if (role == NameRole) {
return person->getName();
} else if (role == AgeRole) {
return person->getAge();
} else if (role == StudentsListRole) {
QList<QVariant> studentsVariantList;
foreach (Student *student, person->getStudents()) {
studentsVariantList<< QVariant::fromValue(student);
}
return studentsVariantList;
} else if (role == StudentsVariantListRole) {
QVariantList studentsVariantList;
foreach (Student *student, person->getStudents()) {
QVariantMap studentMap;
studentMap["id"] = student->id();
studentMap["name"] = student->name();
studentMap["level"] = student->level();
QVariantList booksVariantList;
foreach (Book *book, student->getBooks()) {
QVariantMap bookMap;
bookMap["title"] = book->title();
booksVariantList << bookMap;
}
studentMap["books"] = booksVariantList;
studentsVariantList << studentMap;
}
return studentsVariantList;
}
return QVariant();
}
QHash<int, QByteArray> MyListModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
roles[AgeRole] = "age";
roles[StudentsListRole] = "studentsList";
roles[StudentsVariantListRole] = "studentsVariantList";
return roles;
}
void MyListModel::addPerson(const QVariantMap &data) {
QString name = data["name"].toString();
int age = data["age"].toInt();
Person *person = new Person(name, age);
beginInsertRows(QModelIndex(), rowCount(QModelIndex()), rowCount(QModelIndex()));
m_persons.append(person);
endInsertRows();
}
void MyListModel::updateData(int row, const QVariant &data, const QString &roleName) {
if (roleName == "name") {
m_persons.at(row)->setName(data.toString());
} else if (roleName == "age") {
m_persons.at(row)->setAge(data.toInt());
}
dataChanged(createIndex(row, 0), createIndex(row, 0), {NameRole, AgeRole});
m_persons.at(row)->getStudents().at(0)->setId(666);
m_persons.at(row)->getStudents().at(0)->setName("xiaoming");
m_persons.at(0)->getStudents().at(0)->getBooks().at(0)->setTitle("new title11111111111111111111111111111111111111");
m_persons.at(0)->getStudents().at(0)->getBooks().at(1)->setTitle("new title22222222222222222222222222222222222");
}
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "MyListModel.h"
#include "Person.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<MyListModel>("com.example", 1, 0, "MyListModel");
qmlRegisterType<Person>("com.example", 1, 0, "Person");
engine.load(QUrl(QStringLiteral("../main.qml")));
return QApplication::exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import com.example 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Custom ListModel with Person Example")
ListView {
id: listView
spacing: 10
anchors.fill: parent
model: MyListModel {
id: myListModel
}
delegate: Row {
spacing: 10
Text {
text: "【person】"
}
Text {
text: name
}
Text {
text: age
}
Column {
Repeater {
model: studentsList // studentsVariantList
delegate: Row {
Text {
text: "【student】id = " + modelData.id + ",name = " + modelData.name + ",level = " + modelData.level
}
Column {
Repeater {
model: modelData.books
delegate: Text {
text: "【book】title = " + modelData.title
}
}
}
}
}
}
}
}
Person {
id: pp
name: "dddd"
age: 44
}
Button {
id: addButton
text: pp.name
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
myListModel.addPerson({name: "[" + Math.random() * 100 + "]", age: myListModel.rowCount() + 1});
}
}
Row {
anchors.left: parent.left
anchors.bottom: parent.bottom
Button {
text: "updateName"
onClicked: myListModel.updateData(3, "wlzhou", "name")
}
Button {
text: "updateName"
onClicked: myListModel.updateData(3, 100, "age")
}
}
}
运行效果
