web-dev-qa-db-ja.com

QMLからC ++列挙型にアクセスする方法は?

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

    Style m_style;
    //...
};

.hファイルには上記のコードが含まれています。 QMLを介して上記の列挙型にアクセスする方法

36
Aquarius_Girl

QObjectから派生したクラス(および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();
}

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

    //...
}
41
air-dex

Qt 5.8以降、namespaceから列挙型を公開できます:

名前空間と列挙型を定義します。

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

名前空間を登録します(例:main()で、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
);

QMLファイルで使用します。

import QtQuick 2.0
import my.namespace 1.0

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

参照:

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

22
Maxim Paperno

追加情報( Qt 5.5 より前に文書化されていません):

列挙値名mustは大文字で始まる必要があります。

これは動作します:

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

これはしません:

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

コンパイル時にエラーは発生しません。エラーはQMLエンジンによって無視されます。

18
Richard1403832

Qtは、Qtバージョン5.10以降のQML定義の列挙型もサポートしています。 air-dexによるC++ベースの回答の代替として、QMLを使用して列挙型を作成することもできます。

Style.qml:

import QtQuick 2.0

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

QMLコードで列挙型のみを使用する場合、このソリューションははるかに簡単です。次に、qmlのStyleタイプを使用して上記の列挙型にアクセスできます。次に例を示します。

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")
  }
}

QMLベースの列挙型の別の使用例については、 here を参照してください。

6
GDevT

docs で説明されているように、Q_ENUMSマクロを使用して、mocがenumを認識できるようにします。 docs で説明されているように、enumを使用する前に列挙を「所有する」クラスを登録する必要があります。

Ashifの引用ブロックは、enumがグローバルであるか、_QObject以外の派生クラスによって所有されている場合にのみ有効です。

3
cmannett85

このすべてのソリューションは、この列挙型クラスを信号/スロットのパラメーターとして使用して有効にすることはできません。このコードはコンパイルされますが、QMLでは機能しません。

class DataEmitter : public QObject
{
    Q_OBJECT

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

...

emit setStyle(StyleClass.STYLE_RADIAL);

QMLパート:

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

このコードは、次のようにランタイムエラーを生成します。

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

このコードを機能させるには、レジストリQtメタオブジェクトタイプを追加する必要があります。

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

ここに書かれた詳細: https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys (rus)

0
Xintrea

ここで、QMLのC++クラスのENUMを使用するための非常に素晴らしいソリューションを見つけました。 Qt QMLの列挙-qml.guide 。投稿はとても良かったので、ここでSOコミュニティと共有する義務がありました。IMHOの帰属は常に行われるべきであるため、投稿へのリンクを追加しました。

投稿では基本的に次のことを説明しています。

1)Qt/C++でENUM型を作成する方法:

// statusclass.h

#include <QObject>

class StatusClass
{
    Q_GADGET
public:
    explicit StatusClass();

    enum Value {
        Null,
        Ready,
        Loading,
        Error
    };
    Q_ENUM(Value)
};

2)クラスを「作成できないタイプ」としてQMLエンジンに登録する方法:
(これは、このソリューションを素敵で際立たせる部分です。)

// main.cpp

...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
                                        "Not creatable as it is an enum type.");
...

qmlRegisterUncreatableTypeを使用すると、QMLでStatusClassがインスタンス化されなくなります。ユーザーがこのクラスをインスタンス化しようとすると、警告が記録されます。

qrc:/main.qml:16 Not creatable as it is an enum type.

3)最後に、QMLファイルでENUMを使用する方法:

// main.qml

import QtQuick 2.9
import QtQuick.Window 2.2

import qml.guide 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Component.onCompleted: {
        console.log(StatusClass.Ready); // <--- Here's how to use the ENUM.
    }
}

重要なメモ:
ENUMは、次のようにクラス名で参照することで使用されることになっていますStatusClass.Ready。同じクラスがコンテキストプロパティとしてQMLでも使用されている場合...

// main.cpp

...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
                                        "Not creatable as it is an enum type.");

StatusClass statusClassObj; // Named such (perhaps poorly) for the sake of clarity in the example.
engine.rootContext()->setContextProperty("statusClassObj", &statusClassObj); // <--- like this
...

...その後、クラス名の代わりにコンテキストプロパティでENUMを誤って使用することがあります。

// main.qml

...
Component.onCompleted: {
    // Correct
    console.log(StatusClass.Ready);    // 1

    // Wrong
    console.log(statusClassObj.Ready); // undefined
}
...

人々がこの間違いを犯しがちな理由は、Qt Creatorのオートコンプリート機能は、クラス名とコンテキストプロパティを使用して参照するときの両方でENUMをオプションとしてリストするであるためです。したがって、そのような状況では注意してください。

0
zeFree