c++ qml qt5 qlist qtquick2

Accediendo a C++ QLists desde QML



qt5 qtquick2 (9)

Ah encontré la respuesta (creo, no probada): QQmlListProperty

Hay algunos usos en los ejemplos, por ejemplo, en qtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.* :

Desafortunadamente, solo puedes tener listas de solo lectura en este momento.

Si tengo una lista de cosas en C ++, ¿cómo expongo eso a QML (en Qt5 / QtQuick 2)? Parece que QML solo puede entender las clases derivadas de QObject , lo cual es un problema porque los QObject s no se pueden poner en una QList o copiar. Cómo hago esto:

struct Thing { int size; QString name; }; class ThingManager : public QObject { Q_OBJECT // These macros support QtQuick, in case we one day want to use it to make a slick // interface (when QML desktop components are released). Q_PROPERTY(QList<Thing> things READ things NOTIFY thingssChanged) public: // ... QList<Thing> things() const; // ... };

¿Para que pueda hacer algo como esto en QML?

var a = thingManager.things[0].name;


Alternativamente, puede usar QVariantList ( QList<QVariant> ), cambiará automáticamente a la matriz de JavaScript cuando se pase a QML, y es de lectura y escritura desde C ++ y QML.


Después de más experiencia con QML, he encontrado que la mejor manera de tener listas de cosas es con un QAbstractListModel .

Usted hace que su Thing derive de QObject para que pueda almacenarse en un QVariant (después de registrarlo). Luego puedes devolver la Thing real como el elemento del modelo. Puede acceder a él en un Repeater como model.display.a_property_of_thing . La longitud de la lista está disponible como model.count .

Esto tiene los siguientes pros y contras:

  1. Rápido: no copia la lista completa para acceder a un elemento.
  2. Puede obtener fácilmente animaciones para los cambios en la lista (adición, reorganización y eliminación de elementos).
  3. Es fácil de usar desde QML.
  4. Para habilitar las animaciones para que funcionen, siempre que cambie la lista, debe realizar una contabilidad ligeramente incómoda ( beginInsertRows() etc.)

...

class Things : public QObject { ... }; Q_DECLARE_METATYPE(Thing*) class ThingList : public QAbstractListModel { Q_OBJECT public: explicit ThingList(QObject *parent = 0); ~ThingList(); int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; public slots: // Extra function to get the thing easily from outside Repeaters. Thing* thing(int idx); private: QList<Thing*> mThings; }; int ThingList::rowCount(const QModelIndex& parent) const { return mThings.size(); } QVariant ThingList::data(const QModelIndex& index, int role) const { int i = index.row(); if (i < 0 || i >= mPorts.size()) return QVariant(QVariant::Invalid); return QVariant::fromValue(mThings[i]); } Thing* ThingList::thing(int idx) { if (idx < 0 || idx >= mThings.size()) return nullptr; return mThings[idx]; }


Existe una buena solución, pero no se menciona:

class ThingManager : public QObject { Q_OBJECT // These macros support QtQuick, in case we one day want to use it to make a slick // interface (when QML desktop components are released). Q_PROPERTY(QList<Thing> things MEMBER m_things NOTIFY thingssChanged) // ... private: // ... QList<Thing> m_things; // ... };

Leer y escribir son aplicables. Sin función de llamada costosa y copia de datos. Solo acceso directo a los miembros de la clase en QML:

var a = thingManager.things[0].name;

Para obtener más información, consulte el doc: https://doc-snapshots.qt.io/qt5-dev/properties.html



La respuesta dada por eatyourgreens es correcta. Al implementar su clase de esa manera, puede acceder a tantos descendientes como desee. Un consejo más útil que encontré útil es crear un alias para nuestro modelo dentro del elemento delegado qml.

ListView { anchors.fill: parent model: thing_manager.things delegate: ItemDelagate {} clip: true spacing: 10 }

Y luego, en el ItemDelegate.qml puede crear un alias para que el modelo no use todo el tiempo que model.modelData

Item{ width: 600 height: 200 property var thing: model.modelData Rectangle { anchors.fill: parent color: "red" Text { text: thing.name // or any other field } } }


Me encontré con esta pregunta al intentar solucionar un problema similar, en el que quería usar el código C ++ como fuente modelo en QML. La respuesta dada por TheBootroo me indicó la dirección correcta, pero no funcionó completamente para mí. No tengo la reputación suficiente para responderle directamente (pero sí voté su respuesta).

Estoy usando Qt 5.0.0. Encontré este enlace muy útil.

La definición de ThingManager se debe cambiar de la siguiente manera

class ThingManager : public QObject { Q_OBJECT Q_PROPERTY(QList<QObject*> things READ getThings NOTIFY thingsChanged) public: QList<QObject*> getThings () const { return m_things; } signals: void thingsChanged (); private: QList<QObject*> m_things; };

Tenga en cuenta que cambié el tipo de retorno de getThings a una QList <QObject *>. Sin este cambio, Qt advierte que es "No se puede manejar el tipo de datos no registrado ''QList <Thing *>''".

En el código QML, se puede acceder a las propiedades de Thing a través del modelo como model.modelData.size y model.modelData.name.


Una forma altamente indirecta de lograrlo es esta:

i.) Hacer un modelo en qml

ListModel { id: thingModel ListElement { size: 10 name: "Apple" } }

ii.) Luego proporcione un par de funciones javascript para modificar esta lista, por ejemplo.

function jAppendThing( newSize, newName ) { thingModel.append({"size": nameSize, "name": newName }) } function jClearThing() { thingModel.clear() }

de manera similar jDeleteThing etc.

iii.) Puede leer sobre cómo llamar a las funciones qml desde c ++

iv.) Ejecute un bucle en su lista de C ++ y llame a la función de adición de qml para agregar todos esos datos a la lista de qml también.

v.) En cualquier actualización en la lista lateral de C ++, modifique los datos qml y utilice la función anterior para mantenerlos actualizados.


Usted está bastante equivocado con respecto a QObject, se pueden entregar a una QList, simplemente en la forma de un puntero, como sigue perfectamente:

class Thing : public QObject { Q_OBJECT Q_PROPERTY (int size READ getSize CONSTANT) Q_PROPERTY (QString name READ getName CONSTANT) public: Thing(QObject * parent = NULL) : QObject(parent) {} int getSize () const { return m_size; } QString getName () const { return m_name; } private: int m_size; QString m_name; }; class ThingManager : public QObject { Q_OBJECT Q_PROPERTY(QList<Thing*> things READ getThings NOTIFY thingsChanged) public: QList<Thing*> getThings () const { return m_things; } signals: void thingsChanged (); private: QList<Things*> m_things; };