QML與Qt C++ 交互機制探討與總結

介紹

QML和 C++對象能夠經過,signals,slots和 屬性修改進行交互。對於一個C++對象,任何數據均可以經過Qt的 Meta-Object System暴露給QML(何總方法,後面介紹),同時,任何的QML對象數據經過Meta-object system在C++端直接訪問。
在實際的項目中不少地方會用到QML與Qt C++交互。在這裏總結了若干方法供你們參考,歡迎你們指導和拍磚。
html

在這裏不外乎有三種方法:
1. 把Qt C++中的對象或類型暴露給 QML端,供QML端使用。(官方說法是「嵌入」而非「暴露」,比較文明。- -b)
2. QML中的Signal Handler(至關於Qt C++發送信號給QML端,QML端的Signal Handler進行處理)。
3. 在Qt C++端建立QML對象,既然對象都有了。那你想怎麼樣它就怎麼樣它唄。(沒用過,看起來也不太實用,不過介紹介紹,有用過的同窗留言哈)。
函數

好,咱們開始吧~ui

知識準備

別急,讓咱們先來看看,一些東西,若是您都知道,能夠跳過此節。
QML API有三個主要成員——QDeclarativeEngineQDeclarativeComponentQDeclarativeContext
spa

QDeclarativeEngine提供了QML的運行環境。
QDeclarativeComponent封裝了QML Documents
QDeclarativeContext容許程序使用QML組件顯示數據。
code

QML包含一個很是好用的API——QDeclarativeView。經過它,應用程序能夠很方便的把QML組件嵌入到QGraphicsView中。QDeclarativeView主要用於在應用程序開發過程當中進行快速原型開發。component

暴露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。
htm

QML能夠直接訪問改數據元素的屬性,該屬性由QPROPERTY所申明。
具體實現請參考,示例代碼。
對象

暴露已存在的Qt C++對象給QML

//main.cpp
MyClass myObj;
QDeclarativeEngine *engine=viewer.engine();
QDeclarativeContext *context=engine->rootContext();
context->setContextProperty("myObjectExposeByCXProperty", &myObj);

qml中能夠直接使用myObjectExposeByCxProperty對象。ci

//mainpage.qml
...
Button{
    ...
    id:btn1
    ...
    text: qsTr("PROPERTY") 
    //此處調用myString爲MyClass的QPROPERTY的屬性不是方法,因此沒有括號。
    onClicked: label.text=myObjectExposeByCXProperty.myString;
}
...

註冊Qt C++類類型給QML

另一種方式是註冊類型開發

//main.cpp
qmlRegisterType<MyClass>("RegisterMyType", 1, 0, "MyClassType");

QML中這樣使用

//mainpage.qml
...
import RegisterMyType 1.0
Button{
    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.qml
Button{
    id:btn3
    text: qsTr("emit stringchanged signal")
    onClicked: myObjectExposeByCXProperty.myString="xxxxx";    
}

Qt C++觸發信號

//myclass.cpp
void MyClass::setmyString(QString aString)
{
    if(aString==m_string)
    {
        return;
    }
    m_string=aString;
    emit myStringChanged();
}

鏈接signal handler響應

//mainpage.qml
Connections
{
    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

相關文章
相關標籤/搜索