webentwicklung-frage-antwort-db.com.de

Wie kann man von QML aus auf C++ zugreifen?

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

    Style m_style;
    //...
};

Die .h-Datei enthält den obigen Code. Wie kann über QML auf das oben genannte Enum zugegriffen werden?

31
Aquarius_Girl

Sie können das Enum in eine Klasse einschließen, die von QObject abgeleitet ist (und die Sie für QML freigeben)

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

    //...
}
38
air-dex

Ab Qt 5.8 können Sie Enummen von einer namespace aus anzeigen:

Definieren Sie den Namespace und die Enumeration:

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

Registrieren Sie den Namespace (z. B. in main (), bevor Sie eine Qml-Ansicht/einen Kontext erstellen):

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

Verwenden Sie es in einer QML-Datei:

import QtQuick 2.0
import my.namespace 1.0

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

Verweise:

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

Zusätzliche Informationen (nicht vor Qt 5.5 dokumentiert): 

Ihre Aufzählungsnamen müssen mit einem Großbuchstaben beginnen.

Das wird funktionieren:

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

Das tut nicht:

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

Beim Kompilieren werden keine Fehler angezeigt, sie werden von der QML-Engine einfach ignoriert.

16
Richard1403832

Qt unterstützt auch QML-definierte Aufzählungstypen seit Qt-Version 5.10. Als Alternative zur C++ - basierten Antwort von air-dex können Sie QML jetzt auch verwenden, um Aufzählungstypen zu erstellen:

Style.qml:

import QtQuick 2.0

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

Wenn Sie nur die Aufzählungen in Ihrem QML-Code verwenden möchten, ist diese Lösung wesentlich einfacher. Sie können auf das oben genannte Enum mit dem Style-Typ in qml zugreifen, zum Beispiel:

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

Unter here finden Sie ein weiteres Verwendungsbeispiel für einen QML-basierten Aufzählungstyp.

5
GDevT

Machen Sie das moc mit Hilfe des Makros Q_ENUMS auf Ihr Enum aufmerksam, wie in docs beschrieben. Sie müssen die Klasse registrieren, die das Enum besitzt, bevor verwendet wird, wie in docs beschrieben.

Der Anführungsblock von Ashif ist nur gültig, wenn das Enum global ist oder einer nicht -QObject abgeleiteten Klasse gehört.

3
cmannett85

Alle diese Lösungen können nicht aktiviert werden. Diese Enum-Klasse wurde als Parameter für Signal/Slot verwendet. Dieser Code wird kompiliert, funktioniert aber nicht in QML:

class DataEmitter : public QObject
{
    Q_OBJECT

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

...

emit setStyle(StyleClass.STYLE_RADIAL);

QML-Teil:

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

Und dieser Code generiert Laufzeitfehler wie folgt:

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

Damit dieser Code funktioniert, müssen Sie einen zusätzlichen Registrierungs-Qt-Metaobjekttyp hinzufügen:

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

Weitere Details hier geschrieben: https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys (rus)

0
Xintrea

Ich habe eine sehr gute Lösung für die Verwendung von ENUMs aus der C++ - Klasse in QML gefunden, hier: Aufzählungen in Qt QML - qml.guide . Der Beitrag war so gut, dass ich mich verpflichtet fühlte, ihn hier mit der SO) Community zu teilen. Und IMHO-Zuschreibung sollte immer erfolgen, daher der Link zum Beitrag hinzugefügt.

Der Beitrag beschreibt im Wesentlichen:

1) So erstellen Sie einen ENUM-Typ in Qt/C++:

// statusclass.h

#include <QObject>

class StatusClass
{
    Q_GADGET
public:
    explicit StatusClass();

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

2) So registrieren Sie die Klasse bei der QML-Engine als "Uncreatable Type":
(Dies ist der Teil, der diese Lösung schön und deutlich macht.)

// main.cpp

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

Die Verwendung von qmlRegisterUncreatableType verhindert die Instanziierung von StatusClass in QML. Eine Warnung wird protokolliert, wenn ein Benutzer versucht, diese Klasse zu instanziieren:

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

3) Zum Schluss, wie man ENUM in einer QML-Datei benutzt:

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

Wichtiger Hinweis:
ENUM soll verwendet werden, indem es mit dem Klassennamen wie diesem referenziert wird. StatusClass.Ready. Wenn dieselbe Klasse auch in QML als Kontexteigenschaft verwendet wird ...

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

... dann wird manchmal versehentlich ENUM mit der Eigenschaft context anstelle des Klassennamens verwendet.

// main.qml

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

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

Der Grund, warum Leute dazu neigen, diesen Fehler zu machen, liegt darin, dass das Autocomplete-Feature von Qt Creator ENUM als Option auflistet, sowohl bei der Referenzierung unter Verwendung des Klassennamens als auch der Kontexteigenschaft . Seien Sie also vorsichtig, wenn Sie sich in einer solchen Situation befinden.

0
zeFree