C++與QML互動2:在QML中呼叫C++特性
版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。
本文連結:https://blog.csdn.net/xi_gua_gua/article/details/56991367
QML引擎(QQmlEngine)集成了Qt元物件系統,由QObject派生的所有子類的屬性、方法和訊號等都可以在QML中訪問。QObject是子類有多種辦法將功能暴露給QML訪問:
1、把C++類註冊為一個可例項化的QML物件型別,呼叫方法跟普通的QML型別一樣。
2、把C++類註冊為一個單例型別,可以在QML中匯入單例物件例項
3、把C++類作為上下文屬性或者上下文物件嵌入到QML中
在啟動QML時,會初始化一個QQmlEngine作為QML引擎,然後使用QQmlComponent物件載入QML文件,QML引擎會提供一個預設的QQmlContext物件作為頂層執行的上下文,用來執行QML文件中定義的函式和表示式。
QQmlEngine::rootContext() 返回當前引擎QML的上下文,唯一的,QQmlContext* QQuickView::rootContext()
QQuickItem* QQuickView::rootObject() 返回當前QQuickView的根節點,也就是QML的根節點
QQmlEngine
QQmlEngine類提供了一個QML引擎,用於管理由QML文件定義的物件層次架構,QML提供了一個預設的QML上下文(根上下文,獲取函式QQmlEngine::rootContext())。該上下文是QML表示式的執行環境,並且保證在使用時物件屬效能夠被正確更新。
QQmlEngine可以將全域性設定應用到其管理下的所有QML物件,比如網路通訊:QNetworkAccessManager、全域性永久(整個程式生命週期)儲存的檔案路徑(資源預載入)等
QQmlContext
QQmlContext提供了物件例項化和表示式執行所需要的上下文環境。所有的QML物件都要在特定的上下文中例項化,所有的表示式都要在特定的上下文中執行。上下文以根上下文為主組成層次結構,子上下文繼承父上下文的屬性,修改子上下文的屬性值可以覆蓋父上下文的屬性值。
QQmlContext::setContextProperty()能夠通過名字將資料顯示繫結到上下文,定義、更新上下文的屬性
【注意】使用QQmlContext::setContextProperty()顯示設定物件的屬性會優先於上下文物件的屬性
QQmlComponent
QML文件定義的物件型別可以在執行時使用QQmlComponent類進行例項化,QQmlComponent封裝了QML元件(component)的定義,可以用於載入QML文件,前提條件是需要QQmlEngine例項化QML文件中定義的物件層次結構。
QQmlComponent例項既可以使用C++直接建立,也可以通過Qt.createComponent()函式在QML程式碼中建立
QQmlExpression
動態執行表示式QQmlExpression允許客戶端,在C++中利用一個特定的QML上下文執行JavaScript表示式,表示式執行的結果以QVariant的形式返回,並且遵守QML引擎確定的轉換規則。
二、在QML中使用C++特性
由於QML引擎與Qt元物件系統的緊密整合,QML可以直接訪問QObject子類的屬性、方法、訊號等。
1、QML可以直接讀取和修改C++的屬性
2、QML可以通過JavaScript直接呼叫C++方法
3、QML可以接收C++的訊號
由於QML和C++兩者執行所需要的上下文環境不同,當QML訪問C++資料時,資料的所有權還在C++,特例:就是一個顯示的C++函式呼叫並且返回QObject型別,QML引擎訪問獲取資料的所有權。Qt提供了兩種在QML訪問C++的方法:
法1:在C++中建立一個類,註冊為QML環境的一個型別,在QML中就可以使用這個類建立物件進行訪問。
法2:在C++構建一個物件,把物件通過QQmlContext::setContextProperty()設定到QML的上下文,在QML中可直接使用該物件。
1、把C++建立的類設定到QML上下文
類的要求:(1)QObject類或繼承QObject。(2)呼叫巨集Q_OBJECT。這樣的類能夠進入Qt元物件系統,也會被QML訪問。以下是QML經常訪問的C++型別
(1)QML訪問C++訊號、槽
例子:
建立類: 把類加入QML上下文: QML中訪問C++類
class MakeClass : public QObject QQmlEngine engine; text = qml_make.SetStr("Hello for QML!!!");
{ MakeClass Cmake; //類物件,在下邊設定上下文 qml_make.SlotMake();
Q_OBJECT engine.rootContext->setContextProperty("qml_make",&Cmake)
public:
Q_INVOKABLE void SetStr(QString str);
signals: //C++訊號
void MakeSignal(QString str);
public slots: //C++槽函式
void SlotMake();
};
(2)Q_INVOKABLE 巨集修飾函式,會註冊到Qt元物件系統中,QML可以直接訪問 ${Object}.${method}
定義函式:Q_INVOKABLE void SetStr(QString str);
QML中使用函式:text = qml_make.SetStr("Hello for QML!!!");
(3)Q_ENUMS 巨集修飾列舉,會註冊到Qt元物件系統中,QML可以直接訪問 ${Object}.${method}
定義列舉:Q_ENUMS(m_enum);
QML中使用列舉:text = qml_make.m_enum;
(4)Q_PROPERTY 巨集修飾屬性,會註冊到Qt元物件系統中,QML可以對屬性進行訪問、修改、屬性改變傳送訊號等操作。
定義屬性:Q_PROPERTY(QString Test //定義一個QString型別的Text屬性
READ GetTest //定義讀操作
WRITE SetText //定義寫操作
NOTIFY SlotTextChanged //定義關聯訊號,當屬性發生改變時,觸發訊號
)
QML中使用屬性:text = qml_make.GetText; //呼叫C++中Text屬性的讀操作
Component.onCompleted: {
qml_make.SetText = "Text for QML" //呼叫C++中Text屬性的寫操作
}
2、把C++物件註冊到QML中,當做一個QML物件
QObject 類或 QObject 子類都可以註冊到QML中,在QML中當做一個物件型別進行例項化
註冊QML型別有多個方法:
(1)qmlRegisterSingletonType() 註冊一個單例型別
(2)qmlRegisterType() 註冊一個非單例型別
(3)qmlRegisterTypeNotAvailaible() 註冊一個型別用來佔位
(4)qmlRegisterUncreatableType() 註冊一個具有附加屬性型別
例子:
(1)建立類:
class MakeClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void SetStr(QString str);
Q_PROPERTY(QString Test //定義一個QString型別的Text屬性
READ GetTest //定義讀操作
WRITE SetText //定義寫操作
NOTIFY SlotTextChanged //定義關聯訊號,當屬性發生改變時,觸發訊號
signals: //C++訊號
void MakeSignal(QString str);
public slots: //C++槽函式
void SlotMake();
};
(2)在main函式把類註冊到QML中,註冊函式要放到QML上下文建立之前,否則註冊不成功:
qmlRegisterType<MakeClass>("For.Qt.MakeClass" , 1, 0, "MakeClassQml"); //把類MakeClass註冊到QML中的包為:For.Qt.MakeClass, 版本:1.0, 型別為:MakeClassQml
QQuickView view;
view.setSource( QUrl(QStringLiteral("qrc:///main.qml")));
view.show();
(3)QML引入並且訪問C++物件型別
import For.Qt.MakeClass 1.0
Item
{
MakeClassQml{
SetText : "Hello for QML" //C++屬性的寫操作
}
}
————————————————
版權宣告:本文為CSDN博主「西_瓜_瓜」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/xi_gua_gua/art