我有一个用C ++(逻辑)和QML(UI)编写的应用程序。 在C ++部分,我有一个QML对象的集合(一种事件系统)
这是C ++对象的简化代码:
class Config : public QObject
{
Q_OBJECT
Q_ENUMS(DataEvent)
public:
enum DataEvent {
DataEventUndefined = 0,
DataEventDateChanged
};
~Config();
Q_INVOKABLE void registerToEvent (DataEvent event, QQuickItem *item)
{
p_dataListeners.insert(event,item);
}
private:
QMap<DataEvent,QQuickItem *> p_dataListeners;
}
在QML对象中我称之为C ++函数,它就像魅力一样。这是QML代码的一部分:
Item {
id: myQMLObject
function init() {
Config.registerToEvent(Config.DataEventDateChanged,myQMLObject);
}
function receiveEvent(eventType) {
...
}
}
好的,现在我想调用一个已保存的QML对象的QML函数:
event = Config::DataEventDateChanged;
QMapIterator<DataEvent,QQuickItem *> i(p_dataListeners);
while (i.hasNext()) {
i.next();
if(event == i.key()) {
QQuickItem *item = i.value();
QMetaObject::invokeMethod(item, "receiveEvent",
QGenericReturnArgument(),
Q_ARG(Config::DataEvent, event));
}
}
但我收到此错误:QMetaObject::invokeMethod: No such method MyQMLObject_QMLTYPE_44::receiveEvent(Config::DataEvent)
我做错了什么?
答案 0 :(得分:3)
您必须使用QVariant
作为参数类型:
#include <QApplication>
#include <QtQuick>
class Thing : public QObject
{
Q_OBJECT
Q_ENUMS(DataEvent)
public:
enum DataEvent {
DataEventUndefined = 0,
DataEventDateChanged
};
Thing() {}
public slots:
void registerToEvent(QQuickItem *stuff) {
DataEvent event = Thing::DataEventDateChanged;
QMetaObject::invokeMethod(stuff,
"receiveEvent",
QGenericReturnArgument(),
// Q_ARG(Thing::DataEvent, event));
Q_ARG(QVariant, event));
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
Thing thing;
engine.rootContext()->setContextProperty("thing", &thing);
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
}
#include "main.moc"
<强> main.qml:强>
import QtQuick 2.2
import QtQuick.Window 2.0
Window {
visible: true
width: 300
height: 250
Item {
id: item
Component.onCompleted: {
thing.registerToEvent(item);
}
function receiveEvent(arg) {
print(arg);
}
}
}
这是因为QML中JavaScript函数的参数类型是QVariant
。我们可以通过qmetaobject.cpp的一小部分来验证这一点:
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index accefb1..e39539c 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1455,6 +1455,10 @@ bool QMetaObject::invokeMethod(QObject *obj,
}
if (idx < 0 || idx >= meta->methodCount()) {
+ for (int i = 0; i < meta->methodCount(); ++i) {
+ QMetaMethod method = meta->method(i);
+ qDebug() << method.methodSignature();
+ }
qWarning("QMetaObject::invokeMethod: No such method %s::%s",
meta->className(), sig.constData());
return false;
当方法调用失败时,我们迭代moc已知对象的每个方法。通过上面的示例,输出:
"destroyed(QObject*)"
"destroyed()"
"objectNameChanged(QString)"
"deleteLater()"
"_q_reregisterTimers(void*)"
"childrenRectChanged(QRectF)"
"baselineOffsetChanged(double)"
"stateChanged(QString)"
"focusChanged(bool)"
"activeFocusChanged(bool)"
"activeFocusOnTabChanged(bool)"
"parentChanged(QQuickItem*)"
"transformOriginChanged(TransformOrigin)"
"smoothChanged(bool)"
"antialiasingChanged(bool)"
"clipChanged(bool)"
"windowChanged(QQuickWindow*)"
"childrenChanged()"
"opacityChanged()"
"enabledChanged()"
"visibleChanged()"
"visibleChildrenChanged()"
"rotationChanged()"
"scaleChanged()"
"xChanged()"
"yChanged()"
"widthChanged()"
"heightChanged()"
"zChanged()"
"implicitWidthChanged()"
"implicitHeightChanged()"
"update()"
"_q_resourceObjectDeleted(QObject*)"
"grabToImage(QJSValue,QSize)"
"grabToImage(QJSValue)"
"contains(QPointF)"
"mapFromItem(QQmlV4Function*)"
"mapToItem(QQmlV4Function*)"
"forceActiveFocus()"
"forceActiveFocus(Qt::FocusReason)"
"nextItemInFocusChain(bool)"
"nextItemInFocusChain()"
"childAt(double,double)"
"receiveEvent(QVariant)"
请注意最后一项"receiveEvent(QVariant)"
。