Accès aux listes C++ QL à partir de QML

si j'ai une liste de choses en C++, Comment puis-je l'exposer à QML (en Qt5 / QtQuick 2)? Il semble que QML ne peut comprendre que QObject - classes dérivées, ce qui est un problème parce que QObjects ne peut pas être mis dans un QList ou copié. Comment dois-je faire ceci:

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;

    // ...

};

pour que je puisse faire quelque chose comme ça dans QML:?

var a = thingManager.things[0].name;
22
demandé sur Timmmm 2013-01-12 01:52:39

9 réponses

je suis tombé sur cette question en essayant de corriger un problème similaire, où je voulais utiliser du code C++ comme source modèle dans QML. La réponse donnée par TheBootroo m'a indiqué la bonne direction, mais n'a pas fonctionné pleinement pour moi. Je n'ai pas assez de réputation pour lui répondre directement (mais j'ai pris bonne note de sa réponse).

j'utilise Qt 5.0.0 J'ai trouvé ce lien très utile

La définition de ThingManager devrait être changée comme suit: suit

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;
};

a Noter que j'ai changé le type de retour de getThings à une QList. Sans cette modification, Qt avertit Qu'il est "incapable de gérer le type de données non enregistré 'QList'".

dans le code QML, les propriétés de Thing sont accessibles via le model as model.modelData.taille et modèle.modelData.nom.

21
répondu eatyourgreens 2013-04-05 11:34:36

Alternativement, Vous pouvez utiliser QVariantList (QList<QVariant>), il se transforme automatiquement en tableau JavaScript lorsqu'il est passé à QML, et il est capable de lire et d'écrire à partir de C++ et QML

20
répondu Dickson 2013-01-14 16:20:44

après plus d'expérience avec QML j'ai trouvé la meilleure façon d'avoir des listes de choses est avec un QAbstractListModel.

Vous faites votre Thing tirer QObject donc il peut être stocké dans un QVariant (après inscription). Ensuite, vous pouvez retourner le réel Thing comme l'élément de modèle. Vous pouvez y accéder dans un Repeatermodel.display.a_property_of_thing. La longueur de la liste est disponible en model.count.

C'est la suivante des avantages et des inconvénients:

  1. Fast - il n'a pas copiez la liste entière pour accéder à un élément.
  2. vous pouvez facilement obtenir des animations pour des changements à la liste (Ajout, réarrangement et suppression d'éléments).
  3. il est facile à utiliser à partir de QML.
  4. pour permettre aux animations de fonctionner, chaque fois que vous changez la liste, vous devez faire un peu de comptabilité faffy (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];
}
8
répondu Timmmm 2016-03-07 10:55:01

Ah j'ai trouvé la réponse (je pense, pas testé): QQmlListProperty

Il y a quelques utilisations dans les exemples, par exemple,qtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.*:

malheureusement, vous ne pouvez avoir que des listes en lecture seule pour le moment.

4
répondu Timmmm 2013-01-11 23:39:09

Vous avez tout à fait tort sur QObject, ils peuvent être donnés à une QList, simplement sous la forme d'un pointeur, comme suit fonctionne parfaitement :

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;
};
2
répondu TheBootroo 2013-01-29 08:48:44

La réponse donnée par eatyourgreens est correct. En mettant en œuvre votre classe de cette façon, vous pouvez accéder à autant de descendants que vous le souhaitez. Un autre conseil utile que j'ai trouvé utile est de créer un alias pour notre modèle à l'intérieur de l'élément délégué qml.

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

et puis dans la rubrique Delegate.qml vous pouvez créer un alias pour que le model n'utilise pas tout le temps le 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
        }
    }
}
1
répondu Mr.Coffee 2014-12-10 12:29:46

utilisation de la meilleure façon QQmlListProperty .voir cet exemple simple , je l'espère, vous aider.

Type D'objet et type de propriété exemple

1
répondu Programer 2015-01-21 13:38:15

j'.) Faire un modèle en qml

ListModel 
{
     id: thingModel

     ListElement 
     {
         size: 10
         name: "Apple"
     }     
}

ii.) Puis fournir quelques fonctions javascript pour modifier cette liste par exemple.

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

function jClearThing()
{
    thingModel.clear()
}

iii.) Vous pouvez lire à ce sujet comment appeler les fonctions qml à partir de c++

iv.) Lancez une boucle sur votre liste C++ et appelez la fonction d'ajout de qml pour ajouter toutes ces données dans la liste qml comme bien.

v.) sur toute mise à jour de la liste côté C++, modifiez les données qml en utilisant la fonction ci-dessus pour les garder à jour.

0
répondu Amit Tomar 2013-01-11 23:14:34

Existe bien, mais n'a pas mentionné la solution:

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;
// ...

};

lire et écrire sont applicables. Pas de fonction coûteuse appel et copie de données. Accès direct aux membres de la classe dans QML:

var a = thingManager.things[0].name;
https://doc-snapshots.qt.io/qt5-dev/properties.html

0
répondu fokhagyma 2018-01-23 10:52:02