2

As the Title asked:

    ListModel {
        ListElement {
            name: "Jhon"
            age: 100
        }
    }

where the 'name' and 'age' in ListElement ara arbitrary properties.How did ListElement implement this? This is my own Qml type defined in C++:

Test{
        name:"xxx" //name is not defined with Q_PROPERTY
    }

there is a error:Cannot assign to non-existent property "abc".

Can I implement my own types as the ListElement can do? How?

Thanks!

  • 2
    The best way is to look at the source files: [cpp](https://github.com/qt/qtdeclarative/blob/5.12/src/qml/types/qqmllistmodel.cpp#L771), [h](https://github.com/qt/qtdeclarative/blob/5.12/src/qml/types/qqmllistmodel_p_p.h#L269) – folibis Jan 19 '19 at 14:39
  • I have searched the source files for answer.But I didn't find answer.I found Nothing special about the definition of ListElement type.I guess the answer is not in the definition file,but something about configurations.I don't know. –  Jan 22 '19 at 15:14

2 Answers2

0

As error text suggests, if you want to define properties in C++, you need to declare it with Q_PROPERTY macro and provide methods for it (http://doc.qt.io/qt-5/properties.html).

You may also define properties in QML:

Test {
    property string name: "xxx"
}

ListElement'sname and age are not arbitrary properties, but roles of a model (link).

Sergei Ousynin
  • 170
  • 2
  • 13
0

Let me answer my question!

It seems the usage of ListElement in the ListModel is a special language feature.

As the ListElement Manual says:

List elements are defined like other QML elements except that they contain a collection of role definitions instead of properties. Using the same syntax as property definitions...

According to this, it turns out, the syntax ListElement{roleName:roleValue} in ListModel would not define a instance of type ListElement, but a List element or list item of the ListModel.

I have run the following codes to prove my point.

QML:

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    ListModel {
        objectName: "model"
        ListElement {
            objectName: "element"
            name: "abc"
        }
    }
}

CPP:

#include <QAbstractListModel>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtDebug>
int main(int argc, char* argv[])
{

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    for(const auto &rootObject:engine.rootObjects())
    {
        auto model = rootObject->findChild<QAbstractListModel*>("model");
        qDebug() << model;
        qDebug() << rootObject->findChild<QObject*>("element");

        if(model)
        {
            qDebug() << model->roleNames();
        }
    }

    return app.exec();
}

The output messages:

QML debugging is enabled. Only use this in a safe environment.
QQmlListModel(0x26c4e7c1500, name = "model")
QObject(0x0)
QHash((1, "objectName")(0, "name"))

Seen? The ListModel instantiated an object named model. Whereas the ListElement didn't create an object named element, but made two roles for model object.