Tengo una enumeración definida en un QObject con algunos valores, y estoy registrando la enumeración como QFlags como especifica la documentación de Qt. He registrado la enumeración y el QObject como metatipos a los que puedo acceder sin problemas desde QML.

El problema es que una vez que tengo definida una ranura C ++ QObject que tiene QFlags como argumento, no obtiene un error cuando se llama, sino que pasa el primer valor definido en la enumeración (es decir, su valor es el de la entrada de enumeración con el número 0).

Es difícil de describir, así que creé un pequeño ejemplo de trabajo (usando C ++ 11 / Qt 5.7). Cuando lo ejecuta y hace clic en cualquier lugar de la ventana que se abre, se imprime QFlags<QMLThing::MyEnum>(VALA), aunque en main.qml estoy llamando a thing.doThing(QMLThing.VALC).

Comencé creando una "Aplicación Qt Quick" en QtCreator. Luego agregó una clase llamada "QMLThing". Aquí está el código fuente de cada archivo:

QMLThing.hpp

#ifndef QMLTHING_HPP
#define QMLTHING_HPP

#include <QObject>

class QMLThing : public QObject
{
    Q_OBJECT

public:
    enum MyEnum {
        VALA = 0,
        VALB = 1,
        VALC = 2,
        VALD = 4,
    };

    Q_ENUM(MyEnum)
    Q_DECLARE_FLAGS(MyEnums, MyEnum)

public:
    explicit QMLThing(QObject *parent = 0);

public slots:
    void doThing(QMLThing::MyEnums val);
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QMLThing::MyEnums)
Q_DECLARE_METATYPE(QMLThing::MyEnums)

#endif // QMLTHING_HPP

QMLThing.cpp

#include "QMLThing.hpp"

#include <QDebug>

QMLThing::QMLThing(QObject *parent) : QObject(parent)
{}

void QMLThing::doThing(QMLThing::MyEnums val)
{
    qDebug() << val;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>

#include "QMLThing.hpp"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<QMLThing>("stuff", 1, 0, "QMLThing");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2

import stuff 1.0

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

    MouseArea {
        anchors.fill: parent
        onClicked: {
            thing.doThing(QMLThing.VALC)
        }
    }

    Text {
        text: qsTr("Click here and look in the terminal")
        anchors.centerIn: parent
    }

    QMLThing {
        id: thing
    }
}

Esto se parece mucho a un error, pero tal vez me esté perdiendo algo.

1
YoklJO 26 jul. 2016 a las 04:50

2 respuestas

La mejor respuesta

Falta Q_FLAG(MyEnums):

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>

#include <QObject>

class QMLThing : public QObject
{
    Q_OBJECT

public:
    enum MyEnum {
        VALA = 0,
        VALB = 1,
        VALC = 2,
        VALD = 4,
        VALE = VALC | VALD
    };

    Q_DECLARE_FLAGS(MyEnums, MyEnum)
    Q_FLAG(MyEnums)

public:
    explicit QMLThing(QObject *parent = 0) :
        QObject(parent)
    {
    }

public slots:
    void doThing(QMLThing::MyEnums val)
    {
        qDebug() << val;
    }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QMLThing::MyEnums)
Q_DECLARE_METATYPE(QMLThing::MyEnums)

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<QMLThing>("stuff", 1, 0, "QMLThing");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

#include "main.moc"

main.qml:

import QtQuick 2.7
import QtQuick.Window 2.2

import stuff 1.0

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

    MouseArea {
        anchors.fill: parent
        onClicked: {
            thing.doThing(QMLThing.VALC)
            thing.doThing(QMLThing.VALC | QMLThing.VALD)
        }
    }

    Text {
        text: qsTr("Click here and look in the terminal")
        anchors.centerIn: parent
    }

    QMLThing {
        id: thing
    }
}

Como se menciona aquí, no es necesario utilizar {{X0} }:

Nota: La macro Q_FLAG se encarga de registrar valores de bandera individuales con el sistema de metaobjetos, por lo que no es necesario utilizar Q_ENUM () además de esta macro.

1
Mitch 26 jul. 2016 a las 07:26

No estoy seguro exactamente de lo que está pasando, pero antes que nada:

public:
enum MyEnum {
    VALA,
    VALB,
    VALC,
    VALD,
};

Necesitas eliminar el último coma. También recomendaría establecer al menos la primera enumeración, en un cierto valor, generalmente 0 para que sepa a dónde se dirige, pero no es necesario establecer los siguientes elementos de enumeración, ya que se incrementarán automáticamente desde el último conjunto.

Por último, no estoy del todo seguro acerca de QMLThing.ValC, ¿no debería ser QMLThing::MyEnums::ValC?

0
Nox 26 jul. 2016 a las 02:00