Comment accéder à C++ enum à partir de QML?

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

    Style m_style;
    //...
};

L' .le fichier h a le code ci-dessus. comment accéder à l'enum ci-dessus par QML?

30
demandé sur Kuba Ober 2013-11-20 10:45:34

6 réponses

vous pouvez envelopper l'enum dans une classe qui dérive de QObject (et que vous exposez à QML):

style.php :

#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.rpc:

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

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

    //...

    StyleClass::declareQML();

    //...

    return a.exec();
}

QML Code:

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

    //...
}
35
répondu air-dex 2018-01-30 17:52:57

information additionnelle (non documentée avant Qt 5.5):

les noms de vos valeurs enum commencer par une lettre majuscule.

Cela fonctionne:

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

Cela ne fonctionne pas:

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

vous n'obtiendrez aucun type d'erreur au moment de la compilation, ils sont simplement ignorés par le moteur QML.

15
répondu Richard1403832 2018-01-30 17:56:31

à partir de Qt 5.8 vous pouvez exposer les énumérations à partir d'un namespace:

Définir l'espace de noms enum:

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

enregistrer l'espace de noms(ex. dans main(), avant de créer un Qml Vue/Contexte):

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

L'utiliser dans un QML fichier:

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

13
répondu Max Paperno 2018-05-22 05:31:13

Qt prend également en charge les types d'enum définis par QML depuis la version 5.10 de Qt. Comme alternative à la réponse basée sur C++par air-dex, vous pouvez maintenant aussi 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 enum dans votre code QML, cette solution est beaucoup plus simple. Vous pouvez accéder à l'enum ci-dessus avec le type de Style dans 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
répondu GDevT 2018-03-09 12:43:19

moc conscient de votre enum Q_ENUMS macro, comme décrit dans la docs. Vous devez enregistrer la classe qui possède l'enum avant il est utilisé, comme décrit dans la docs.

le bloc de devis D'Ashif n'est valide que si l'enum est un global ou appartient à un non-QObject classe dérivée.

2
répondu cmannett85 2017-06-21 10:05:58

toutes ces solutions ne peuvent pas être activées utilisé cette classe d'enum comme paramètre pour signal / slot. Ce code compilera, mais ne fonctionnera pas dans QML:

class DataEmitter : public QObject
{
    Q_OBJECT

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

...

emit setStyle(StyleClass.STYLE_RADIAL);

QML-part:

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

Et ce code générer d'erreur à l'exécution, comme ceci:

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

Pour que ce code fonctionne, vous devez registre supplémentaires Qt metaobject type:

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

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

0
répondu Xintrea 2018-08-23 18:46:35