Qt行動裝置 App開發(六):QML與C++的互動

來源:互聯網
上載者:User

Qt行動裝置 App開發(六):QML與C++的互動

Qt行動裝置 App開發(六):QML與C++的互動

 

       上一篇文章講到了在Qt Quick中實現情境切換的一種可能的方法,情境切換是諸如遊戲等應用在內必須要面臨的技術痛點,所以情境切換並沒有通行的方法,根據自己的使用習慣進行設計即可。

       本文主要介紹的是如何使用QML和C++進行互動,難度稍微偏大,適合有經驗的Qt開發人員進行學習交流。

       Qt 5吸收了Qt 4的declarative模組的優點,對底層進行了更改,建立了QPA層,隔離了不同作業系統API和上層Qt代碼,同時QML/QtQuick也可以順利在不同平台上運行。另外由於考慮到讓Qt程式接入不同的庫函數,因此Qt開放了介面讓QML層和C++代碼進行互動。之前已經有較多介紹QML與C++互動的文章了,本文僅作為一種有益的補充,更多相關的知識可以查詢Qt協助文檔或向我留言。

       本文的例子在Qt 5.3.1中順利編譯運行通過。

原創文章,反對未聲明的引用。原部落格地址:http://blog.csdn.net/gamesdev/article/details/37359873

       首先一個較為簡單的方法就是註冊內容屬性(Context Property),讓QML訪問C++的變數。代碼如下:


#include <QApplication>#include <QQmlApplicationEngine>#include <QQmlContext>int main(int argc, char *argv[]){    QApplication app(argc, argv);    QQmlApplicationEngine engine;    engine.rootContext( )->setContextProperty(                "Greeting",                QObject::tr( "Hello QML from C++" ) );    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));    return app.exec();}

然後在QML中簡單地調用”Greeting”變數名就可以順利訪問了。


import QtQuick 2.2import QtQuick.Controls 1.1ApplicationWindow{    visible: true    width: 640    height: 480    title: qsTr("測試QML於C++的互動")    menuBar: MenuBar    {        Menu        {            title: qsTr("檔案")            MenuItem            {                text: qsTr("退出")                onTriggered: Qt.quit( );            }        }    }    Text    {        text: qsTr("本例用來測試QML和C++的互動")        anchors.right: parent.right        anchors.bottom: parent.bottom    }    Text    {        text: Greeting        anchors.centerIn: parent    }}


示範程式的如下:

       本例重要的部分是QQmlContext執行個體指標。它通過QQmlApplicationEngine::rootContext()來獲得,也可以通過QQmlApplicationEngine:: contextForObject(constQObject * object)來獲得。在QQmlObject建立的時候,都會執行個體化一個QQmlContext,用來支援為運行環境提供的內容屬性。

       使用內容屬性可以讓QML訪問C++資料,那麼如何使用QML來訪問C++的函數呢?這裡我們在C++中註冊QML類或者單例來讓QML來獲得訪問C++函數的機會。首先介紹一下如何將QML中註冊C++類到QML中。首先需要定義一個C++類繼承於QObject,然後這麼寫:


#ifndef CPLUSPLUSCLASS_H#define CPLUSPLUSCLASS_H#include <QObject>class CPlusPlusClass: public QObject{    Q_OBJECT    Q_PROPERTY( int rating READ rating )public:    explicit CPlusPlusClass( QObject* pParent = Q_NULLPTR ):        QObject( pParent )    {        m_Rating = 5;    }    Q_INVOKABLE void method( void )    {        qDebug( "[C++]%s is called.", __FUNCTION__ );    }    int rating( void ) { return m_Rating; }private:    int m_Rating;};#endif // CPLUSPLUSCLASS_H

然後再main.cpp中需要調用qmlRegisterType()模板函數來註冊C++類到QML中,一個典型的用法如下:


#include <QApplication>#include <QQmlApplicationEngine>#include <QtQml>#include "CPlusPlusClass.h"int main(int argc, char *argv[]){    QApplication app(argc, argv);    // 首先註冊一下類    qmlRegisterType<CPlusPlusClass>(                "CPlusPlus.Test",           // 統一資源識別項                1,                          // 主要版本                0,                          // 次版本                "CPlusPlusType" );          // QML類名稱    QQmlApplicationEngine engine;    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));    return app.exec();}

       最後在QML中就可以順利地訪問C++類的屬性和方法了:


import QtQuick 2.2import QtQuick.Controls 1.1import CPlusPlus.Test 1.0ApplicationWindow{    visible: true    width: 640    height: 480    title: qsTr("測試QML於C++的互動")    menuBar: MenuBar    {        Menu        {            title: qsTr("檔案")            MenuItem            {                text: qsTr("退出")                onTriggered: Qt.quit( );            }        }    }    Text    {        text: qsTr("本例用來測試QML和C++的互動")        anchors.right: parent.right        anchors.bottom: parent.bottom    }    CPlusPlusType    {        id: theType    }    MouseArea    {        anchors.fill: parent        onClicked:        {            console.log( "[qml] Rating is: " + theType.rating );            theType.method( );        }    }}

點擊表單,控制台運行結果如下:

qml: [qml] Ratingis: 5

[C++]method iscalled.

如果不想在QML和C++環境中建立多個QObject或者說想要更加方便地訪問C++的方法,那麼可以考慮註冊一個單例類,註冊單例類和註冊普通的類差不多,但也有一些顯著的區別,首先建立這樣一個繼承於QObject的類,代碼如下:


#ifndef CPLUSPLUSCLASS_H#define CPLUSPLUSCLASS_H#include <QObject>class CPlusPlusClass: public QObject{    Q_OBJECT    Q_PROPERTY( int rating READ rating )public:    explicit CPlusPlusClass( QObject* pParent = Q_NULLPTR ):        QObject( pParent )    {        m_Rating = 5;    }    Q_INVOKABLE void method( void )    {        qDebug( "[C++]%s is called.", __FUNCTION__ );    }    int rating( void ) { return m_Rating; }private:    int m_Rating;};#endif // CPLUSPLUSCLASS_H

然後關鍵在main.cpp中,除了調用qmlRegisterSingletonType()模板函數外,還需要寫一個靜態全域的註冊函數。代碼如下:


#include <QApplication>#include <QQmlApplicationEngine>#include <QtQml>#include "CPlusPlusSingleton.h"// 註冊單例函數static QObject* CPlusPlusSingletonRegisterFunc(        QQmlEngine* pQMLEngine,        QJSEngine* pJSEngine ){    Q_UNUSED( pQMLEngine );    Q_UNUSED( pJSEngine );    CPlusPlusSingleton* pSingleton = new CPlusPlusSingleton;    return pSingleton;}int main(int argc, char *argv[]){    QApplication app(argc, argv);    // 首先註冊一下單例    qmlRegisterSingletonType<CPlusPlusSingleton>(                "CPlusPlus.Test",                   // 統一資源識別項                1,                                  // 主要版本                0,                                  // 次版本                "CPlusPlusSingleton",               // 單例名稱                CPlusPlusSingletonRegisterFunc );   // 函數名    QQmlApplicationEngine engine;    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));    return app.exec();}

就這樣,C++的部分就完成了。接下來在QML中就很簡單了:


import QtQuick 2.2import QtQuick.Controls 1.1import CPlusPlus.Test 1.0ApplicationWindow{    visible: true    width: 640    height: 480    title: qsTr("測試QML於C++的互動")    menuBar: MenuBar    {        Menu        {            title: qsTr("檔案")            MenuItem            {                text: qsTr("退出")                onTriggered: Qt.quit( );            }        }    }    Text    {        text: qsTr("本例用來測試QML和C++的互動")        anchors.right: parent.right        anchors.bottom: parent.bottom    }    MouseArea    {        anchors.fill: parent        onClicked:        {            console.log( "[qml] Rating is: " + CPlusPlusSingleton.rating );            CPlusPlusSingleton.method( );        }    }}

點擊表單,控制台結果如下:

qml: [qml] Ratingis: 5

[C++]method iscalled.

       大家可以根據需要選擇是否在C++中註冊QML類和註冊C++單例來獲得相對應的特性。

       在我的第一款獨立遊戲《吃藥了》中,為了順利地接入廣告SDK,需要寫C++代碼來保證讓QML能夠訪問到C++的函數,廣告顯示效果如下:

本文參加了CSDN博文大賽,請大家支援我,為我投一票!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.