介紹
QML和 C++對象可以通過,signals,slots和 屬性修改進行互動。對於一個C++對象,任何資料都可以通過Qt的 Meta-Object System暴露給QML(何總方法,後面介紹),同時,任何的QML對象資料通過Meta-object system在C++端直接存取。
在實際的項目中很多地方會用到QML與Qt C++互動。在這裡總結了若干方法供大家參考,歡迎大家指導和拍磚。
在這裡不外乎有三種方法:
1. 把Qt C++中的對象或類型暴露給 QML端,供QML端使用。(官方說法是“嵌入”而非“暴露”,比較文明。- -b)
2. QML中的Signal Handler(相當於Qt C++發送訊號給QML端,QML端的Signal Handler進行處理)。
3. 在Qt C++端建立QML對象,既然對象都有了。那你想怎麼樣它就怎麼樣它唄。(沒用過,看起來也不太實用,不過介紹介紹,有用過的同學留言哈)。
好,我們開始吧~
知識準備
別急,讓我們先來看看,一些東西,如果您都知道,可以跳過此節。
QML API有三個主要成員——QDeclarativeEngine,QDeclarativeComponent和QDeclarativeContext。
QDeclarativeEngine提供了QML的運行環境。
QDeclarativeComponent封裝了QML Documents。
QDeclarativeContext允許程式使用QML組件顯示資料。
QML包含一個非常好用的API——QDeclarativeView。通過它,應用程式可以很方便的把QML組件嵌入到QGraphicsView中。QDeclarativeView主要用於在應用程式開發過程中進行快速原型開發。
暴露Qt C++的對象或類型給QML
建立需要暴露給QML的資料類型
#ifndef MYCLASS_H#define MYCLASS_H#include <QObject>#include <QString>class MyClass : public QObject{ Q_OBJECT Q_PROPERTY(QString myString READ myString WRITE setmyString NOTIFY myStringChanged)public: explicit MyClass(QObject *parent = 0); Q_INVOKABLE QString getMyString();signals: void myStringChanged();public slots: void setmyString(QString aString); QString myString();private: QString m_string;};#endif // MYCLASS_H
若你想資料元素中的方法可以被QML直接調用有2種方法:
1. 在函數申明前添加 Q_INVOKABLE 宏。
2. 申明成public slots。
QML可以直接存取改資料元素的屬性,該屬性由QPROPERTY所申明。
具體實現請參考,範例程式碼。
暴露已存在的Qt C++對象給QML
//main.cppMyClass myObj;QDeclarativeEngine *engine=viewer.engine();QDeclarativeContext *context=engine->rootContext();context->setContextProperty("myObjectExposeByCXProperty", &myObj);
qml中可以直接使用myObjectExposeByCxProperty對象。
//mainpage.qml...Button{ ... id:btn1 ... text: qsTr("PROPERTY") //此處調用myString為MyClass的QPROPERTY的屬性不是方法,所以沒有括弧。 onClicked: label.text=myObjectExposeByCXProperty.myString;}...註冊Qt C++類類型給QML
另外一種方式是註冊類型
//main.cppqmlRegisterType<MyClass>("RegisterMyType", 1, 0, "MyClassType");
QML中這樣使用
//mainpage.qml...import RegisterMyType 1.0Button{ id:btn2 ... text: qsTr("INOVKABLE") //此處調用的時INVOKABLE的方法,不是屬性,所以有括弧。 onClicked: label.text=myclassExposeByRegType.getMyString();}//建立對象,由於QML是解釋執行的,所以放後面也沒什麼關係。MyClassType{ id:myclassExposeByRegType}
步驟:
1. 匯入import。
2. 建立對象。
3. id直接使用。
QML中的Signal Handler
還是使用上面的那例子,在qml中點擊按鈕控制項,改變其中對象的字串,這時候在Qt C++中發送一個signal訊號給qml端,qml端接收到使用signal handler響應,改變label2的值。具體代碼如下。
qml中修改string的值。
//mainpage.qmlButton{ id:btn3 text: qsTr("emit stringchanged signal") onClicked: myObjectExposeByCXProperty.myString="xxxxx"; }
Qt C++觸發訊號
//myclass.cppvoid MyClass::setmyString(QString aString){ if(aString==m_string) { return; } m_string=aString; emit myStringChanged();}
串連signal handler響應
//mainpage.qmlConnections{ target: myObjectExposeByCXProperty onMyStringChanged:label2.text="Signal handler received" }Qt C++中直接調用QML的函數
同樣的QML的函數也可以被Qt C++端調用。
所有的QML函數都通過meta-object system暴露Qt C++端,在Qt C++端可以使用QMetaObject::invokeMethod()方法直接調用。下面就是這樣的一個例子。
// MyItem.qml import QtQuick 1.0 Item { function myQmlFunction(msg) { console.log("Got message:", msg) return "some return value" } }
// main.cpp QDeclarativeEngine engine; QDeclarativeComponent component(&engine, "MyItem.qml"); QObject *object = component.create(); QVariant returnedValue; QVariant msg = "Hello from C++"; QMetaObject::invokeMethod(object, "myQmlFunction", Q_RETURN_ARG(QVariant, returnedValue), Q_ARG(QVariant, msg)); qDebug() << "QML function returned:" << returnedValue.toString(); delete object;
注意:QMetaObject::invokeMethod()方法中的參數Q_RETURN_ARG()和Q_ARG()都被定義為QVariant類型,此類型是QML函數的的參數和傳回值的通用資料類型。
轉自:http://www.developer.nokia.com/Community/Wiki/QML%E4%B8%8EQt_C%2B%2B_%E4%BA%A4%E4%BA%92%E6%9C%BA%E5%88%B6%E6%8E%A2%E8%AE%A8%E4%B8%8E%E6%80%BB%E7%BB%93