2015-08-07 1 views
4

J'ai écrit une classe client (héritant de QObject) en C++ et enregistré son type avec succès avec QML. Actuellement, je crée des objets de cette classe statiquement en C++ et je stocke un pointeur dans un modèle qui implémente QAbstractListModel. En QML, je peux accéder parfaitement aux objets en tant qu'éléments du Modèle.Créer un objet C++ personnalisé dans QML et le stocker dans un modèle C++

Le customObject est un objet non visuel.

Je visualise dans une autre partie de l'application GUI (QML) les objets dans un ListView avec un délégué.

Cependant maintenant je voudrais créer dynamiquement des objets de ma classe personnalisée dans QML et les stocker également dans le modèle. C'est là que je me bats. J'espère que je pourrais créer un customObject comme ceci:

import com.myProject.myCustomStuff 1.0 

... 


Button{ 
    id: createObjBtn 
    text: "create new CustomObj" 
    onClicked:{ 
     var obj = MyCustomObj; 
     myObjectManager.addObj(obj); // object holding the implemented QAbstactListModel 
     console.log(typeof(obj)); // returns [Object object] 
     console.log(Qt.isQtObject(obj)) // returns false 
    } 
} 

J'apprécierais vos pensées. Peut-être que quelqu'un sait comment le faire correctement?

Merci!

Update 1

Comme demandé par Simon-Warta, voici la mise en œuvre de Constructor MyCustomObj.

MyCustomObj.cpp

MyCustomObj::MyCustomObj(QObject *parent) : QObject(parent) 
{ 
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); 
} 

Répondre

1

Vous confondez l'intention de la fonctionnalité des classes. Le QAbstractListModel est conçu comme une enveloppe autour d'un conteneur, oui, vous pouvez placer le conteneur dans la classe dérivée QAbstractListModel, mais vous ne devez pas vraiment, le conteneur peut être à peu près n'importe quelle classe C++, pas nécessairement QObject dérivé, il peut être juste un QVector<Something> que vous pouvez atteindre à partir du modèle via un pointeur.Ce qui est bon pour les cas où vous avez beaucoup d'objets, et pas tous besoin d'avoir des modèles tout le temps, puisque ces modèles sont assez lourds. Vous n'avez pas vraiment besoin de vous préoccuper de la propriété, laissez cela du coté C++, de même pour la création de l'objet, un slot appelé qui ajoute le nouvel objet au conteneur tout en utilisant le modèle beginInsertRows() et endInsertRows() afin que toutes les vues seront notifiées pour mettre à jour efficacement, le nouvel objet doit également être créé dans cet emplacement, vous pouvez transmettre toutes les données nécessaires à partir de QML, assurez-vous que toutes les données sont enregistrées avec le méta système Qt peut fonctionner avec QVariant pour l'interopérabilité QML-C++.

Il devrait être quelque chose comme:

myObjectManager.create(/* any needed data goes here */) 

Et create() transmet des données éventuelles au côté C, où vous créez l'objet, appelez beginInsertRows(), ajoutez l'objet au stockage sous-jacent du modèle, puis appelez endInsertRows() et vous avez terminé.

Je préférerais garder la propriété du côté C++ (et je ne veux pas dire explicitement), où j'ai le contrôle dessus. Qt aspire d'une manière ou d'une autre à la propriété d'objets partagée entre C++ et QML. Idéalement, il devrait y avoir une seule classe de pointeurs partagés qui fonctionnera à la fois sur C++ et sur QML, de sorte que l'objet est supprimé une fois que toutes les références à celui-ci ont disparu. Mais ce n'est pas la «méthode Qt» - les pointeurs partagés Qt ne fonctionnent pas avec QML, pas plus que les pointeurs partagés C++ standard, il existe en fait une classe de référence partagée entièrement différente pour QML, qui ne fait même pas partie de l'API publique IIRC, conception très laide et à courte vue qui ne fait qu'élargir l'écart entre C++ et QML et le facteur de désagrément associé.

+0

merci! Cela semble être un très bon conseil. Je vais créer en C++ une méthode d'usine pour ma classe myObjectManager, puis gérer complètement la création, le stockage et la suppression d'objets en C++. – DH1TW

+0

Je suis confus par "Le QAbstractListModel est conçu comme une enveloppe autour d'un conteneur, oui, vous pouvez mettre le conteneur dans la classe dérivée de QAbstractListModel, mais vous n'avez pas vraiment à" ... pouvez-vous expliquer cela plus? Je pense que nous avons toujours mis un conteneur à l'intérieur (dans sa classe dérivée) et c'est un peu comme l'emballer, mais vous semblez dire que ce sont deux choses différentes? – zar

+0

@zar - par exemple, dans mon cas, j'ai des millions d'objets, mais je n'ai pas besoin de les visualiser tous en même temps. Donc, dans ce cas, j'utilise un modèle de "pièce jointe" qui ne contient pas les données, fournit simplement une interface de modèle de liste pour une vue de liste pour y accéder. L'intention de la classe de modèle est de fournir un accès aux données, l'emplacement réel des données n'est pas pertinent. – dtech

1

Je ne sais pas si cela est le chemin le plus court, mais cela devrait le faire pour vous. Je commence par les bases pour ces autres électeurs.

MyCustomObj.h

class MyCustomObj : public QObject 
{ 
    Q_OBJECT 

public: 
    // ... 

    Q_INVOKABLE void funfunction(); 

MyCustomObj.cpp

void MyCustomObj::funfunction() 
{ 
    qDebug("Fun with QML"); 
} 

main.cpp

qmlRegisterType<MyCustomObj>("com.myProject.myCustomStuff", 1, 0, "MyCustomObj"); 

app.qml

import com.myProject.myCustomStuff 1.0 

ApplicationWindow { 
    id: mainWindow 

    Component { 
     id: myComponent 

     MyCustomObj { 

     } 
    } 

    Component.onCompleted: { 
     var obj = myComponent.createObject(mainWindow) 
     if (!obj) console.error("Error creating object") 

     console.log(typeof(obj)) 
     console.log(Qt.isQtObject(obj)) 

     obj.funfunction() 
    } 

} 

createObject prend éventuellement les propriétés à transmettre au composant.

Stockage

Puisque vous êtes responsable de la suppression des objets maintenant, je recommande d'utiliser des pointeurs partagés, tels que les objets sont détruits lorsque la liste est détruite.

Votre mise en œuvre de QAbstactListModel, nous allons l'appeler MyModel a une fonction d'addition comme ça:

#include <memory> // for std::shared_ptr 

class MyModel : public QAbstractListModel 
{ 
    Q_OBJECT 

public: 

    // .. 

    Q_INVOKABLE addObj(MyCustomObj* obj) 
    { 
     objectlist_.append(std::shared_ptr<MyCustomObj>(obj)); 
    } 

private: 
    QList<std::shared_ptr<MyCustomObj>> objectlist_ 
} 
+0

merci pour votre réponse. Mais je pense que ce n'est pas ce que je cherchais. Je veux stocker le myCustomObj généré dynamiquement dans un modèle C++ (qui implémente QAbstractListModel). Ce modèle contient des références à tous les <* MyCustomObjs>. – DH1TW

+0

Eh bien, ce serait un pas de plus. Avez-vous pensé à la propriété et à la gestion des ressources? Souhaitez-vous que Javscript ou Cpp possèdent les objets générés? –

+0

Oui, dans le constructeur de MyCustomObj, j'attribue spécifiquement la propriété à C++. – DH1TW