項目用C++和qml聯合編程有段時間了,今天抽時間再次復習了,特寫下筆記。
在QML中使用C++類型或是屬性,有兩種方法:
a.C++實現一個類,繼承自QObject或是是QObject的派生類,並使用Q_OBJECT宏,注冊為qml的一個類型。
b.C++中構造一個對象,這個對象繼承自QObject或是是QObject的派生類,並使用Q_OBJECT宏,將這個對象設置為qml的上下文屬性。
關於更多在QML中訪問C++類型的內容,我們可以百度或是買本書看看,下面我們來具體看看如何將類、類的方法、類的屬性、枚舉注冊到QML的元對象系統,既可以在QML中訪問。
1)注冊到方法到QML。定義一個成員函數,在申明時,在方法前面加上Q_INVOKABLE宏即可,如:
Q_INVOKABLE void requestChangedLanguage(LANGUAGE_TYPE type); //注冊一個方法到QMl
2)注冊一個枚舉到QML。首先定義一個枚舉,使用Q_ENUMS將枚舉注冊到QML元對象中即可。如:
typedef enum { LANGUAGE_CH, LANGUAGE_EN, LANHUAGE_NUM, }LANGUAGE_TYPE; Q_ENUMS(LANGUAGE_TYPE) //注冊枚舉到QML
3)注冊一個屬性到QML。通過Q_PROPERTY宏定義一個屬性到QML即可,如:
Q_PROPERTY(QString strTag READ getStrTag NOTIFY strTagChanged) //注冊有個屬性到QML,Q_PROPERTY有多個參數,我們只說我們常用參數
4)注冊一個C++類到QML和注冊一個對象為QML上下文屬性。我們注冊一個一個類型到QML,有多種方法,我們就說比較常用的通過qmlRegisterType,這是個模板函數,注冊方式如下:
qmlRegisterType<CLanguuage>("Test.Com", 1, 0, "ZH"); //將C++類CLanguuage注冊到QML
同樣,注冊一個對象對qml,也很簡單,直接代碼:
QQmlApplicationEngine* engine = new QQmlApplicationEngine(); m_pRoot->rootContext()->setContextProperty("myLanguage", this); //將C++對象作為屬性注冊到QML
其實說來說去,都很簡單,下面是Demo代碼,看起來很直觀:
clanguage.h
#ifndef CLANGUUAGE_H #define CLANGUUAGE_H #include <QObject> #include <QTranslator> #include <QtQml> #include <QQmlEngine> #include <QDebug> #include <QCoreApplication> #include <QQmlApplicationEngine> #include <QString> class CLanguuage : public QObject { Q_OBJECT public: typedef enum { LANGUAGE_CH, LANGUAGE_EN, LANHUAGE_NUM, }LANGUAGE_TYPE; Q_ENUMS(LANGUAGE_TYPE) //注冊枚舉到QML explicit CLanguuage(QObject *parent = 0); explicit CLanguuage(QQmlEngine* engine, QObject *parent = 0); ~CLanguuage(); Q_PROPERTY(QString strTag READ getStrTag NOTIFY strTagChanged) //注冊有個屬性到QML,Q_PROPERTY有多個參數,我們只說我們常用參數 Q_INVOKABLE void requestChangedLanguage(LANGUAGE_TYPE type); //注冊一個方法到QMl QString getStrTag(void); signals: void strTagChanged(void); public slots: private: QQmlEngine* m_pRoot; QTranslator* m_tran; }; #endif // CLANGUUAGE_H
clanguage.cpp
#include "clanguage.h" CLanguuage::CLanguuage(QObject *parent) : QObject(parent) ,m_pRoot(NULL) { m_tran = new QTranslator(); m_pRoot->rootContext()->setContextProperty("myLanguage", this); //將C++對象作為屬性注冊到QML } CLanguuage::CLanguuage(QQmlEngine* engine, QObject *parent) : QObject(parent) ,m_pRoot(engine) { m_tran = new QTranslator(); m_pRoot->rootContext()->setContextProperty("myLanguage", this); //將C++對象作為屬性注冊到QML } CLanguuage::~CLanguuage() { if(NULL != m_tran) { delete m_tran; m_tran = NULL; } } void CLanguuage::requestChangedLanguage(LANGUAGE_TYPE type) { qDebug()<<" [zhaohui] void CLanguuage::requestChangedLanguage() type = "<<type; QString strPath; switch(type) { case CLanguuage::LANGUAGE_CH: strPath = "language_ch.qm"; break; case CLanguuage::LANGUAGE_EN: strPath = "language_en.qm"; break; default: strPath = "language_en.qm"; break; } if(NULL != m_tran) { bool ret = false; qDebug()<<" void CLanguuage::requestChangedLanguage() strPath = "<<strPath; ret = m_tran->load(strPath); qDebug()<<" void CLanguuage::requestChangedLanguage() A ret = "<<ret; ret = false; ret = QCoreApplication::installTranslator(m_tran); emit strTagChanged(); qDebug()<<" void CLanguuage::requestChangedLanguage() B ret = "<<ret; } } QString CLanguuage::getStrTag(void) { return ""; }
main.cpp
#include <QGuiApplication> #include "clanguage.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine* engine = new QQmlApplicationEngine(); qmlRegisterType<CLanguuage>("Test.Com", 1, 0, "ZH"); //將C++類CLanguuage注冊到QML CLanguuage lang(engine); lang.requestChangedLanguage(CLanguuage::LANGUAGE_CH ); engine->load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.3 import QtQuick.Window 2.2 import QtQuick.Controls 1.2 import Test.Com 1.0 Window { visible: true width: 440 height: 360 Button { id:chineseBtn width:220 height:30 text:qsTrId("CON_TXT002")+myLanguage.strTag onClicked: { myLanguage.requestChangedLanguage(ZH.LANGUAGE_CN)//qml中訪問C++方法 console.log(" zh chinese button clicked") } } Button { id:englishBtn x:220 width:220 height:30 text:qsTrId("CON_TXT003")+myLanguage.strTag onClicked: { myLanguage.requestChangedLanguage(ZH.LANGUAGE_EN)//qml中訪問C++枚舉 console.log(" zh english button clicked.") } } Text { font.pixelSize: 24 text: qsTrId("CON_TXT001")+myLanguage.strTag//qml中訪問C++屬性 color: "#6e16e0" anchors.centerIn: parent } }
上面代碼在Qt5.6.2和Qt5.3.2上運行OK,但是有幾個需要注意的地方:
1)上面代碼運行是沒有問題的,這個Demo是做的一個跨平台(window/linux)的多語言的Demo,要實現中文切換還需要幾個.ts和.qm文件,具體將在下一篇筆記中詳細描述。
2)本文僅實現如何講C++注冊到QML,怎么樣在C++中訪問QML對象,這個可以自己百度下,也很簡單,但從項目維護性角度看,一般不建議既可以在C++中訪問QML對象,同時又可以在QML中訪問C++。建議僅僅在QML中訪問C++就可以了,這樣其實完全可以滿足項大多數項目需求。