web-dev-qa-db-fra.com

Comment accéder à l'énumération C++ à partir de QML?

class StyleClass : public QObject {
public:
    typedef enum
        {
            STYLE_RADIAL,
            STYLE_ENVELOPE,
            STYLE_FILLED
        }  Style;

    Style m_style;
    //...
};

Le fichier .h a le code ci-dessus. Comment accéder à l'énumération ci-dessus via QML?

31
Aquarius_Girl

Vous pouvez envelopper l'énum dans une classe dérivée de QObject (et que vous exposez à QML):

style.hpp:

#ifndef STYLE_HPP
#define STYLE_HPP

#include <QtGlobal>
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
    // Qt 4
    #include <QDeclarativeEngine>
#else
    // Qt 5
    #include <QQmlEngine>
#endif

// Required derivation from QObject
class StyleClass : public QObject
{
    Q_OBJECT

    public:
        // Default constructor, required for classes you expose to QML.
        StyleClass() : QObject() {}

        enum EnStyle
        {
            STYLE_RADIAL,
            STYLE_ENVELOPE,
            STYLE_FILLED
        };
        Q_ENUMS(EnStyle)

        // Do not forget to declare your class to the QML system.
        static void declareQML() {
            qmlRegisterType<StyleClass>("MyQMLEnums", 13, 37, "Style");
        }
};

#endif    // STYLE_HPP

main.cpp:

#include <QApplication>
#include "style.hpp"

int main (int argc, char ** argv) {
    QApplication a(argc, argv);

    //...

    StyleClass::declareQML();

    //...

    return a.exec();
}

Code QML:

import MyQMLEnums 13.37
import QtQuick 2.0    // Or 1.1 depending on your Qt version

Item {
    id: myitem

    //...

    property int item_style: Style.STYLE_RADIAL

    //...
}
38
air-dex

A partir de Qt 5.8, vous pouvez exposer des énumérations provenant de namespace:

Définir l'espace de noms et l'énumération:

#include <QObject>

namespace MyNamespace
{
    Q_NAMESPACE         // required for meta object creation
    enum EnStyle {
        STYLE_RADIAL,
        STYLE_ENVELOPE,
        STYLE_FILLED
    };
    Q_ENUM_NS(EnStyle)  // register the enum in meta object data
}

Enregistrez l’espace de noms (par exemple, dans main (), avant de créer une vue/un contexte Qml):

qmlRegisterUncreatableMetaObject(
  MyNamespace::staticMetaObject, // static meta object
  "my.namespace",                // import statement (can be any string)
  1, 0,                          // major and minor version of the import
  "MyNamespace",                 // name in QML (does not have to match C++ name)
  "Error: only enums"            // error in case someone tries to create a MyNamespace object
);

Utilisez-le dans un fichier QML:

import QtQuick 2.0
import my.namespace 1.0

Item {
    Component.onCompleted: console.log(MyNamespace.STYLE_RADIAL)
}

Références:

https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/

http://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableMetaObject

http://doc.qt.io/qt-5/qobject.html#Q_ENUM_NS

18
Max Paperno

Informations complémentaires (non documentées avant Qt 5.5 ): 

Votre nom de valeur enum doit commencer par une lettre majuscule.

Cela fonctionnera:

enum EnStyle
{
    STYLE_RADIAL,
    STYLE_ENVELOPE,
    STYLE_FILLED
};
Q_ENUMS(EnStyle)

Cela ne veut pas:

enum EnStyle
{
    styleRADIAL,
    styleENVELOPE,
    styleFILLED
};
Q_ENUMS(EnStyle)

Vous n'obtiendrez aucun type d'erreur au moment de la compilation, elles sont simplement ignorées par le moteur QML.

16
Richard1403832

Qt prend également en charge les types enum définis par QML depuis Qt version 5.10. En guise d'alternative à la réponse C++ par air-dex, vous pouvez désormais également utiliser QML pour créer des types enum:

Style.qml:

import QtQuick 2.0

QtObject {
  enum EnStyle {
    STYLE_RADIAL,
    STYLE_ENVELOPE,
    STYLE_FILLED
  }
}

Si vous avez seulement l'intention d'utiliser les énumérations de votre code QML, cette solution est beaucoup plus simple. Vous pouvez accéder à l'énumération ci-dessus avec le type de style en qml puis, par exemple:

import VPlayApps 1.0
import QtQuick 2.9

App {

  property int enStyle: Style.EnStyle.STYLE_RADIAL

  Component.onCompleted: {
    if(enStyle === Style.EnStyle.STYLE_ENVELOPE)
      console.log("ENVELOPE")
    else
      console.log("NOT ENVELOPE")
  }
}

Voir ici pour un autre exemple d'utilisation d'un type enum basé sur QML.

5
GDevT

Mettez la variable moc au courant de votre énumération à l'aide de la macro Q_ENUMS, comme décrit dans la docs . Vous devez enregistrer la classe qui 'possède' l'énum avant que il soit utilisé, comme décrit dans le docs _.

Le bloc de devis d'Ashif n'est valide que si l'énumération est globale ou appartient à une classe dérivée non -QObject.

3
cmannett85

Toutes ces solutions ne pouvaient pas être utilisées utilisaient cette classe d'énumération en tant que paramètre pour signal/slot. Ce code compile, mais ne fonctionne pas dans QML:

class DataEmitter : public QObject
{
    Q_OBJECT

public:
    ...
signals:
    void setStyle(StyleClass::EnStyle style);
}

...

emit setStyle(StyleClass.STYLE_RADIAL);

Partie QML:

Connections {
    target: dataEmitter
    onSetStyle: {
         myObject.style=style
    }
}

Et ce code génère une erreur d’exécution, comme ceci:

IndicatorArea.qml:124: Error: Cannot assign [undefined] to int

Pour que ce code fonctionne, vous devez disposer d'un type de métaobjet Qt de registre supplémentaire:

qRegisterMetaType<StyleClass::EnStyle>("StyleClass.EnStyle");

Plus de détails écrits ici: https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys (rus)

0
Xintrea