2014-06-11 3 views
2

C++ (로직) 및 QML (UI)로 작성된 앱이 있습니다. 는 C++에서 일부 I는 QML 개체 (이벤트 시스템의 종류)C++ invokeMethod가 QML 메소드에 액세스 할 수 없습니다.

이 C++ 객체의 단순화 된 코드의 모음이 있습니다

QML 객체의
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; 
} 

내가 전화를 C++ 기능을하고 그것은처럼 작동 매력. 이 QML 코드의 일부입니다

Item { 
    id: myQMLObject 
    function init() { 
     Config.registerToEvent(Config.DataEventDateChanged,myQMLObject); 
    } 
    function receiveEvent(eventType) { 
    ... 
    } 
} 

OK, 지금은 저장 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)

무엇 나는 틀린가?

답변

2

당신은 인수 유형으로 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에서 자바 스크립트 함수의 인수 유형이 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에 알려진 개체의 모든 방법을 반복. 위의 예제에서이 결과는 다음과 같이 출력됩니다. 에주의하십시오. "receiveEvent(QVariant)".

+0

OK, thanks @Mitch! 나는 내 직장 컴퓨터에 도착하면 그것을 시도 할 것이다. 그렇다면 등록 된 타입을 사용하는 것은 불가능하지만 QVariant에만 함수 매개 변수로 형변환했다는 말입니까? – folibis

+0

가능할 수 있습니다. 내가 말했듯이, 나는 잘 모르겠다. – Mitch

+0

QVariant가 필요한 이유에 대한 설명으로 내 대답을 업데이트했습니다. – Mitch

관련 문제