程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> QML與Qt C++ 交互機制探討與總結,qmlqt

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

編輯:C++入門知識

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


介紹

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.cpp
MyClass 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.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端,然後利用signals-slots 進行連接,並傳遞消息。具體步驟如下
1 創建自己的對象,如果你的對象是要顯示在QML端,可以繼承QDeclarativeItem,如果只是一個控制類,而不需要顯示在QML端,只需要繼承QObject。這裡用到數據綁定請參考Using QML Bindings in C++ Applications

#include<QObject>
class NetConnectController : public QObject
{
Q_OBJECT
Q_PROPERTY(int status READ status WRITE setStatus NOTIFY statusChanged) 
public:
explicit NetConnectController(QObject *parent = 0);
 
void Ready()
{
emit statusChanged( m_status);
}
signals:
void statusChanged(int aStatus);
private:
int status() const;
void setStatus(int aStatus);
private :
//表示網絡不同的狀態
int m_status;
};


2 暴露你的對象給QML

..... 
NetConnectController netController
QDeclarativeEngine * engine = viewer.engine();
(engine->rootContext())->setContextProperty("NetController",&netController);
.....

3在QML中連接Signal-slot

......
 
Connections
{
target: NetController
onStatusChanged:changeStatus(aStatus)//Call JS Function
}
......

注意:上面的onStatusChanged 命名格式 “on”+"Qt C++中的signal名字"。在QML端可以直接使用Qt C++端的參數。例如上面的"aStatus"。


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函數的的參數和返回值的通用數據類型。
更多例程可以在SDK的安裝目錄中:\QtSDK\Examples\4.7\declarative\tutorials\extending 看到。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved