在 QML 信号中公开枚举
Exposing an enum in a QML signal
我在接收带有 qml 中正确枚举类型的信号 mySignal
时遇到问题。我认为我做对了一切:
- 枚举在一个单独的 class 中,派生自
QObject
- 枚举已注册
Q_ENUMS
- 包含枚举的 class 已注册
qmlRegisterUncreatableType
- 信号在class中定义,也是一个
QObject
并且也注册在qmlRegisterUncreatableType
值得注意的事实:
- 运行 程序在从 main.qml 调用的槽中打印日志,但是发出的信号在 qml 中没有收到。
- 取消注释 textclass.cpp 中的发射允许在 QML 中接收信号,但是与枚举值的比较没有触发。
为什么我没有收到 QML 中枚举的信号,为什么我不能与 QML 中的枚举值进行比较,即使它是用 Q_ENUMS 公开的?
我在 Qt 缺陷页面上看到了关于枚举的缺陷报告,因此我了解到 Qt 中对枚举的支持并非坚如磐石。但是,我真的很想能够将值与 QML 中的枚举值进行比较,以获取接收到的信号,而目前我还没有。由于某种原因,输入到 mySlot 中的值很乐意接受信号处理程序中无法识别的相同枚举值。下面的代码清单。
使用 Ubuntu 上的 Qt 5.4。
error.h:
#ifndef ERROR_H
#define ERROR_H
#include <QObject>
#include <QtQml>
class Error : public QObject
{
Q_OBJECT
Q_ENUMS(Type)
public:
explicit Error(QObject *parent = 0) {Q_UNUSED(parent)};
~Error() {};
static void RegisterTypes(void)
{
qmlRegisterUncreatableType<Error>("Types", 1, 0, "Error", "Error class uncreatable");
}
enum Type {
OK = 0,
FILE_ERROR
};
};
#endif // ERROR_H
testclass.h:
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include <QVariant>
#include <QDebug>
#include "error.h"
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
~TestClass();
static void RegisterTypes(void)
{
qmlRegisterUncreatableType<TestClass>("TestClass", 1, 0, "TestClass", "TestClass uncreatable");
};
signals:
void mySignal(Error::Type arg);
void mySignal(int arg);
public slots:
void mySlot(QVariant arg);
};
#endif // TESTCLASS_H
testclass.cpp:
#include "testclass.h"
TestClass::TestClass(QObject *parent) : QObject(parent)
{
}
TestClass::~TestClass()
{
}
void TestClass::mySlot(QVariant arg)
{
qDebug() << "mySlot called" << arg.toInt();
int retval = static_cast<int>(arg.toInt());
emit mySignal(static_cast<Error::Type>(retval));
// emit mySignal(retval);
}
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "error.h"
#include "testclass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Error::RegisterTypes();
TestClass::RegisterTypes();
TestClass* tPtr = new TestClass();
engine.rootContext()->setContextProperty("_t", tPtr);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.qml:
import QtQuick 2.4
import QtQuick.Window 2.2
import Types 1.0
import TestClass 1.0
Window {
visible: true
width: button.width + 20
height: button.height + 20
Rectangle {
id: button
width: theText.width + 20
height: theText.height + 20
anchors.margins: 10
anchors.centerIn: parent
border.width: 3
Connections {
target: _t
onMySignal: {
console.log("onMySignal: ", arg)
if (arg == Error.OK) {
console.log("OK")
}
else if (arg == Error.FILE_ERROR) {
console.log("FILE_ERROR")
}
else {
console.log("UNDEFINED")
}
}
}
Text {
id: theText
anchors.centerIn: parent
text: "press me!"
font.pixelSize: 30
}
MouseArea {
anchors.fill: parent
onClicked: _t.mySlot(Error.FILE_ERROR)
onPressed: button.scale = 0.9
onReleased: button.scale = 1.0
}
}
}
这有两个问题。
第一个问题:
Error::Type 未在 Meta 类型系统中注册,
需要在错误 class 声明后添加以下行:
Q_DECLARE_METATYPE(错误::类型)
第二题:
是我为错误选择了名称 'Error'
class 我注册的时候。这与内置类型发生冲突。这
注册需要改成这样:
qmlRegisterUncreatableType("Types", 1, 0, "ErrorClass", "Error class uncreatable");
(QML 代码也需要更新以反映这一点
当然。)
更改这两项解决了问题,现在可以在 QML 代码中正确接收信号。
我在接收带有 qml 中正确枚举类型的信号 mySignal
时遇到问题。我认为我做对了一切:
- 枚举在一个单独的 class 中,派生自
QObject
- 枚举已注册
Q_ENUMS
- 包含枚举的 class 已注册
qmlRegisterUncreatableType
- 信号在class中定义,也是一个
QObject
并且也注册在qmlRegisterUncreatableType
值得注意的事实:
- 运行 程序在从 main.qml 调用的槽中打印日志,但是发出的信号在 qml 中没有收到。
- 取消注释 textclass.cpp 中的发射允许在 QML 中接收信号,但是与枚举值的比较没有触发。
为什么我没有收到 QML 中枚举的信号,为什么我不能与 QML 中的枚举值进行比较,即使它是用 Q_ENUMS 公开的?
我在 Qt 缺陷页面上看到了关于枚举的缺陷报告,因此我了解到 Qt 中对枚举的支持并非坚如磐石。但是,我真的很想能够将值与 QML 中的枚举值进行比较,以获取接收到的信号,而目前我还没有。由于某种原因,输入到 mySlot 中的值很乐意接受信号处理程序中无法识别的相同枚举值。下面的代码清单。
使用 Ubuntu 上的 Qt 5.4。
error.h:
#ifndef ERROR_H
#define ERROR_H
#include <QObject>
#include <QtQml>
class Error : public QObject
{
Q_OBJECT
Q_ENUMS(Type)
public:
explicit Error(QObject *parent = 0) {Q_UNUSED(parent)};
~Error() {};
static void RegisterTypes(void)
{
qmlRegisterUncreatableType<Error>("Types", 1, 0, "Error", "Error class uncreatable");
}
enum Type {
OK = 0,
FILE_ERROR
};
};
#endif // ERROR_H
testclass.h:
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include <QVariant>
#include <QDebug>
#include "error.h"
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
~TestClass();
static void RegisterTypes(void)
{
qmlRegisterUncreatableType<TestClass>("TestClass", 1, 0, "TestClass", "TestClass uncreatable");
};
signals:
void mySignal(Error::Type arg);
void mySignal(int arg);
public slots:
void mySlot(QVariant arg);
};
#endif // TESTCLASS_H
testclass.cpp:
#include "testclass.h"
TestClass::TestClass(QObject *parent) : QObject(parent)
{
}
TestClass::~TestClass()
{
}
void TestClass::mySlot(QVariant arg)
{
qDebug() << "mySlot called" << arg.toInt();
int retval = static_cast<int>(arg.toInt());
emit mySignal(static_cast<Error::Type>(retval));
// emit mySignal(retval);
}
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "error.h"
#include "testclass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Error::RegisterTypes();
TestClass::RegisterTypes();
TestClass* tPtr = new TestClass();
engine.rootContext()->setContextProperty("_t", tPtr);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.qml:
import QtQuick 2.4
import QtQuick.Window 2.2
import Types 1.0
import TestClass 1.0
Window {
visible: true
width: button.width + 20
height: button.height + 20
Rectangle {
id: button
width: theText.width + 20
height: theText.height + 20
anchors.margins: 10
anchors.centerIn: parent
border.width: 3
Connections {
target: _t
onMySignal: {
console.log("onMySignal: ", arg)
if (arg == Error.OK) {
console.log("OK")
}
else if (arg == Error.FILE_ERROR) {
console.log("FILE_ERROR")
}
else {
console.log("UNDEFINED")
}
}
}
Text {
id: theText
anchors.centerIn: parent
text: "press me!"
font.pixelSize: 30
}
MouseArea {
anchors.fill: parent
onClicked: _t.mySlot(Error.FILE_ERROR)
onPressed: button.scale = 0.9
onReleased: button.scale = 1.0
}
}
}
这有两个问题。
第一个问题:
Error::Type 未在 Meta 类型系统中注册, 需要在错误 class 声明后添加以下行:
Q_DECLARE_METATYPE(错误::类型)
第二题:
是我为错误选择了名称 'Error' class 我注册的时候。这与内置类型发生冲突。这 注册需要改成这样:
qmlRegisterUncreatableType("Types", 1, 0, "ErrorClass", "Error class uncreatable");
(QML 代码也需要更新以反映这一点 当然。)
更改这两项解决了问题,现在可以在 QML 代码中正确接收信号。