【QT】QML與C++混合編程詳解__Linux

來源:互聯網
上載者:User

1QMLC++為什麼要混合編程

QML與C++為什麼要混合編程,簡單來說,就是使用QML高效便捷地構建UI,而C++則用來實現商務邏輯和複雜演算法,下面介紹了兩者間互動的方法與技巧。


2QML訪問C++概述

Qt整合了QML引擎和Qt元對象系統,使得QML很容易從C++中得到擴充,在一定的條件下,QML就可以訪問QObject衍生類別的成員,例如訊號、槽函數、枚舉類型、屬性、成員函數等。

QML訪問C++有兩個方法:一是在Qt元對象系統中註冊C++類,在QML中執行個體化、訪問。二是在C++中執行個體化並設定為QML內容屬性,在QML中直接使用。與後者相比,前者可以使C++類在QML中作為一個資料類型,例如函數參數類型或屬性類型,也可以使用其枚舉類型、單例等,功能更強大。


3、如何?可以被QML訪問的C++

C++類要想被QML訪問,首先必須滿足兩個條件:一是派生自QObject類或QObject類的子類,二是使用Q_OBJECT宏。QObject類是所有Qt對象的基類,作為Qt物件模型的核心,提供了訊號與槽機制等很多重要特性。Q_OBJECT宏必須在private區(C++預設為private)聲明,用來聲明訊號與槽,使用Qt元對象系統提供的內容,位置一般在語句塊首行。下面例子在QtCreator3.1.2中建立,Projects選擇QtQuickApplication,工程名為Gemini,Component選擇QtQuick2.2,然後在自動產生的檔案中添磚加瓦。

訊號與槽——

(1)添加標頭檔Gemini.h

#ifndef GEMINI_H#define GEMINI_H// Gemini.h#include <QObject>#include <QDebug>class Gemini : public QObject{    Q_OBJECTsignals:    void begin();public slots:    void doSomething() {        qDebug() << "Gemini::doSomething() called";    }};#endif // GEMINI_H

Gemini類中的訊號begin()和槽doSomething()都可以被QML訪問。槽必須聲明為public或protected,訊號在C++中使用時要用到emit關鍵字,但在QML中就是個普通的函數,用法同函數一樣,訊號處理器形式為on<Signal>,Signal首字母大寫。訊號不支援重載,多個訊號的名字相同而參數不同時,能夠被識別的只是最後一個訊號,與訊號的參數無關。

(2)修改main.cpp

// main.cpp#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QtQml>#include <Gemini.h>int main(int argc, char *argv[]){    QGuiApplication app(argc, argv);    qmlRegisterType<Gemini>("Union.Lotto.Gemini", 1, 0, "Gemini");    QQmlApplicationEngine engine;    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));    return app.exec();}

這裡把Gemini類註冊(qmlRegisterType)到了Qt元對象系統,當然也可以先執行個體化再設定為QML內容屬性,相關內容將在後面詳細介紹。

(3)修改main.qml

// main.qmlimport QtQuick 2.2import QtQuick.Window 2.1import Union.Lotto.Gemini 1.0Window {    visible: true    width: 360; height: 360    title: "Union Lotto Game"    color: "white"    MouseArea {        anchors.fill: parent        onClicked: {            gemini.begin()        }    }    Gemini {        id: gemini        onBegin: doSomething()    }}

Gemini類註冊到Qt元對象系統後,並且在QML檔案中匯入(import),關鍵字Gemini就可以在當前QML檔案中當作一種QML類型來用了。例子中有個MouseArea,單擊滑鼠時會發送begin()訊號,進而調用doSomething()槽函數。

枚舉類型——

(1)修改標頭檔Gemini.h

#ifndef GEMINI_H#define GEMINI_H// Gemini.h#include <QObject>#include <QDebug>class Gemini : public QObject{    Q_OBJECT    Q_ENUMS(BALL_COLOR)public:    Gemini() : m_ballColor(BALL_COLOR_YELLOW) {        qDebug() << "Gemini::Gemini() called";    }    enum BALL_COLOR {        BALL_COLOR_YELLOW,        BALL_COLOR_RED,        BALL_COLOR_BLUE,        BALL_COLOR_ALL    };signals:    void begin();public slots:    void doSomething(BALL_COLOR ballColor) {        qDebug() << "Gemini::doSomething() called with" << ballColor;        if(ballColor != m_ballColor) {            m_ballColor = ballColor;            qDebug() << "ball color changed";        }    }private:    BALL_COLOR m_ballColor;};#endif // GEMINI_H

Gemini類中添加了public的BALL_COLOR枚舉類型,這個枚舉類型要想在QML中使用,就用到了Q_ENUMS()宏。

(2)修改main.qml

// main.qmlimport QtQuick 2.2import QtQuick.Window 2.1import Union.Lotto.Gemini 1.0Window {    visible: true    width: 360; height: 360    title: "Union Lotto Game"    color: "white"    MouseArea {        anchors.fill: parent        onClicked: {            gemini.begin()        }    }    Gemini {        id: gemini        onBegin: doSomething(Gemini.BALL_COLOR_RED)    }}

在QML中使用枚舉類型的方式是<CLASS_NAME>.<ENUM_VALUE>,例如Gemini.BALL_COLOR_RED。

成員函數——

(1)修改標頭檔Gemini.h

#ifndef GEMINI_H#define GEMINI_H// Gemini.h#include <QObject>#include <QDebug>class Gemini : public QObject{    Q_OBJECT    Q_ENUMS(BALL_COLOR)public:    Gemini() : m_ballColor(BALL_COLOR_YELLOW) {        qDebug() << "Gemini::Gemini() called";    }    enum BALL_COLOR {        BALL_COLOR_YELLOW,        BALL_COLOR_RED,        BALL_COLOR_BLUE,        BALL_COLOR_ALL    };    Q_INVOKABLE void stop() {        qDebug() << "Gemini::stop() called";    }signals:    void begin();public slots:    void doSomething(BALL_COLOR ballColor) {        qDebug() << "Gemini::doSomething() called with" << ballColor;        if(ballColor != m_ballColor) {            m_ballColor = ballColor;            qDebug() << "ball color changed";        }    }private:    BALL_COLOR m_ballColor;};#endif // GEMINI_H

Gemini類中添加了成員函數stop(),在QML中訪問的前提是public或protected成員函數,且使用Q_INVOKABLE宏,位置在函數傳回型別的前面。

(2)修改main.qml

// main.qmlimport QtQuick 2.2import QtQuick.Window 2.1import Union.Lotto.Gemini 1.0Window {    visible: true    width: 360; height: 360    title: "Union Lotto Game"    color: "white"    MouseArea {        anchors.fill: parent        onClicked: {            gemini.begin()            gemini.stop()        }    }    Gemini {        id: gemini        onBegin: doSomething(Gemini.BALL_COLOR_RED)    }}

在QML中訪問C++的成員函數的形式是<id>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.