1. 程式人生 > >Qt5.8 QML和C++混合程式設計的兩種方式(附帶原始碼)

Qt5.8 QML和C++混合程式設計的兩種方式(附帶原始碼)

Qt5.8  QML和C++混合程式設計的兩種方式(附帶原始碼)

編譯環境:win10 專業版    Qt5.8   

  Qt 提供了兩種在 QML 環境中使用 C++ 物件的方式:

上手敲一下,很快就能理解 
             

點選開始,中間的圖形開始變化,上面顯示時間,點選停止,不再變化,點選RGB,應用這個演算法,按鈕顯示為下一個演算法,退出按鈕退出程式

************************************************************************************************************************************************************************************************************************************************

1.C++ 中實現一個類,註冊到 QML 環境中, QML 環境中使

用該型別建立物件

QML中使用C++物件

(1)實現可以匯出的C++類 

colormaker.h

#ifndef COLORMAKER_H
#define COLORMAKER_H

#include <QObject>
#include <QColor>
#include <QTimerEvent>

class ColorMaker : public QObject
{
    Q_OBJECT
    //  如果你要匯出的類定義了想在 QML 中使用列舉型別,可以使用 Q_ENUMS 巨集將該列舉註冊到元物件系統中。
    Q_ENUMS(generate)
    //Q_PROPERTY 巨集用來定義可通過元物件系統訪問的屬性,通過它定義的屬性,可以在 QML 中訪問、修改,也可以在屬性變化時發射特定的訊號。
    //READ   宣告一個讀取屬性的函式,該函式一般沒有引數,返回定義的屬性。
    //WRITE  [可選]宣告一個設定屬性的函式。它指定的函式,只能有一個與屬性型別匹配的引數,必須返回 void 。
    //NOTIFY [可選]給屬性關聯一個訊號(該訊號必須是已經在類中宣告過的),當屬性的值發生變化時就會觸發該訊號。訊號的引數,一般就是你定義的屬性。
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
    Q_PROPERTY(QColor timeColor READ timeColor )

public:
    explicit ColorMaker(QObject *parent = 0);

    //列舉該變數 (5中顏色的演算法)
    enum generate{
        randomRGB,
        randomRed,
        randomGreen,
        randomBlue,
        increase  //(顏色變化演算法為)直線增長模式
    };

    QColor color() const;
    void setColor(const QColor &color);
    QColor timeColor() const;

    //在定義一個類的成員函式時使用 Q_INVOKABLE 巨集來修飾,就可以讓該方法被元物件系統呼叫。這個巨集必須放在返回型別前面。
    Q_INVOKABLE generate algorithm() const;              //返回型別為列舉型別GenerateAlgorithm;  這是一個演算法函式
    Q_INVOKABLE void setAlgouthm(generate algorithm);    //設定為具體使用哪一個顏色的演算法

signals:
    //定義colorChanged() / currentTime() 兩個訊號
    void colorChanged(const QColor &color);              //顏色改變的訊號
    void currentTimer(const QString &strTime);           //當前時間的訊號

public slots:
    //定義了 start() / stop() 兩個槽
    void start();
    void stop();

protected:
    void timerEvent(QTimerEvent *event);                 //時間事件

private:
    generate myGenerate;   //具體使用的哪一種演算法
    QColor myColor;        //現在的顏色
    int colorTimer;        //定時器的ID
};

#endif // COLORMAKER_H








colormaker.cpp

#include "colormaker.h"
#include <QDateTime>
#include <QColor>

ColorMaker::ColorMaker(QObject *parent)
    : QObject(parent)
    , myGenerate(randomRGB)   //初始化一個隨機的顏色演算法
    , myColor(Qt::black)      //初始化賦值為黑色
    , colorTimer(0)
{
    qsrand(QDateTime::currentDateTime().toTime_t());
}

//單純的呼叫該函式, 確定設定顏色順便會發射顏色改變的訊號
QColor ColorMaker::color() const
{
    return myColor;
}

//顏色由當前時間作為引數來生成
void ColorMaker::setColor(const QColor &color)
{
    myColor = color;
    emit colorChanged(myColor);
}

//顏色由當前時間作為引數來生成
QColor ColorMaker::timeColor() const
{
    QTime time = QTime::currentTime();    //獲取當前現在的時間
    int r = time.hour();
    int g = time.minute();
    int b = time.second();
    return QColor::fromRgb(r, g, b);
}

//傳送出去一個(演算法)的值 [確定是使用哪一種演算法,RGB? Green? Red? Blue? ]
ColorMaker::generate ColorMaker::algorithm() const
{
    return myGenerate;
}

//賦值給類成員
void ColorMaker::setAlgouthm(ColorMaker::generate algorithm)
{
    myGenerate = algorithm;
}

//啟動時間
void ColorMaker::start()
{
    if(colorTimer == 0)
    {
        colorTimer = startTimer(1000);
    }
}

//停止計時器的使用
void ColorMaker::stop()
{
    if(colorTimer > 0)
    {
        killTimer(colorTimer);    //終止計時器,銷燬
        colorTimer = 0;
    }
}


//timerEvent事件訊息
void ColorMaker::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == colorTimer)
    {
        switch (myGenerate) {
        case randomRGB:
            myColor.setRgb(qrand()%255, qrand()%255, qrand()%255);
            break;
        case randomRed:
            myColor.setRed(qrand()%255);
            break;
        case randomGreen:
            myColor.setGreen(qrand()%255);
            break;
        case randomBlue:
            myColor.setBlue(qrand()%255);
            break;
        default:
        {
            int r = myColor.red() + 10;
            int g = myColor.green() + 10;
            int b = myColor.blue() + 10;
            myColor.setRgb(r%255, g%255, b%255);
        }
            break;
        }

        //發射這兩個訊號
        emit colorChanged(myColor);
        emit currentTimer(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    }
    else
    {
        timerEvent(event);
    }
}


main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <colormaker.h>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    // 註冊一個 QML 型別 ;註冊一個單例型別,然後就可以在qml裡面呼叫了
    //qmlRegisterType() 的第一個引數 uri ,讓你指定一個唯一的包名,類似 Java 中的那種,
    //一是用來避免名字衝突,而是可以把多個相關類聚合到一個包中方便引用。
    //比如我們常寫這個語句 "import QtQuick.Controls 1.1" ,其中的 "QtQuick.Controls" 就是包名 uri ,而 1.1 則是版本,是 versionMajor 和 versionMinor 的組合。
    //qmlName 則是 QML 中可以使用的類名。
    qmlRegisterType<ColorMaker>("qt.an.colormaker", 1, 0, "ColorMaker");  //只增加了這一句

    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0    //控制版本
import QtQuick.Layouts 1.0     //佈局版本
import qt.an.colormaker 1.0    //匯入自定義的C++的類, 這是其自定義的包名和主、次版本號

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("2018_2_26_qml與C++混合程式設計")

    Text {
        id: timeLabel;
        anchors.top: parent.top;
        anchors.horizontalCenter: parent.horizontalCenter;
        font.pixelSize: 40;

    }

    //在這裡呼叫了C++類, 建立了一個介意供qml使用的C++物件
    ColorMaker {
        id: colorMaker;
    }

    //中間顯示顏色變化的矩形
    Rectangle {
        id:colorRect;
        anchors.centerIn: parent;
        width: 300;
        height: 300;
        color: "Green";
    }

    //開始按鈕
    Button {
        id: start;
        text: "start";
        anchors.left: parent.left;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            colorMaker.start();
        }
    }

    //結束按鈕
    Button {
        id: stop;
        text: "stop";
        anchors.left: start.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            colorMaker.stop();
        }
    }

    //Javascript函式
    function changetAlgorithm(button, algorithm) {
        switch(algorithm)
        {
        case 0:
            button.text = "RGB";
            break;
        case 1:
            button.text = "Red";
            break;
        case 2:
            button.text = "Green";
            break;
        case 3:
            button.text = "Blue";
            break;
        default:
            button.text = "increase";
            break;
        }
    }

    //顏色演算法按鈕
    Button {
        id: colorAlgorithm;
        text: "RGB";
        anchors.left: stop.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            var algorithm = (colorMaker.algorithm() +1) % 5;
            changetAlgorithm(colorAlgorithm, algorithm);     //changetAlgorithm是後面的Javascript函式
            colorMaker.setAlgouthm(algorithm);
        }
    }

    //退出按鈕
    Button {
        id: quit;
        text: "quit";
        anchors.left: colorAlgorithm.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            Qt.quit();
        }
    }

    //關聯控制元件colorMaker 和 槽函式onCurrentTimer
    Connections {
        target: colorMaker;              //接收事件的物件
        onCurrentTimer: {                //收到事件時的處理函式
            timeLabel.text = strTime;    //strTime從currentTimer裡傳送過來的
            timeLabel.color = colorMaker.timeColor;
        }
    }

    Connections {
        target: colorMaker;
        onColorChanged: {
            colorRect.color = colorMaker.color;
        }
    }


}



專案名稱:2018_2_26_qmlANDc

 

******************************************************************************************************************

2.在 C++ 中構造一個物件,將這個物件設定為 QML 的上下文

屬性,在 QML 環境中直接使用改屬性

colormaker.h  不變,和上面一樣

colormaker.cpp  不變,和上面一樣

main.cpp  有變化

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <colormaker.h>
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("colorMaker", new ColorMaker);   //新增加的一句,用於註冊可以被qml使用的C++物件
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}



main.qml  有變化, 但是是只有兩處需要註釋掉

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
//import qt.an.colormaker 1.0    //不需要匯入這個包

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("2018_2_26_qml與C++混合程式設計")

    Text {
        id: timeLabel;
        anchors.top: parent.top;
        anchors.horizontalCenter: parent.horizontalCenter;
        font.pixelSize: 40;

    }

//不需要在這裡建立這個物件了
//    ColorMaker {
//        id: colorMaker;
//    }

    Rectangle {
        id:colorRect;
        anchors.centerIn: parent;
        width: 300;
        height: 300;
        color: "Green";
    }

    Button {
        id: start;
        text: "start";
        anchors.left: parent.left;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            colorMaker.start();
        }
    }

    Button {
        id: stop;
        text: "stop";
        anchors.left: start.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            colorMaker.stop();
        }
    }

    //Javascript函式
    function changetAlgorithm(button, algorithm) {
        switch(algorithm)
        {
        case 0:
            button.text = "RGB";
            break;
        case 1:
            button.text = "Red";
            break;
        case 2:
            button.text = "Green";
            break;
        case 3:
            button.text = "Blue";
            break;
        default:
            button.text = "increase";
            break;
        }
    }

    Button {
        id: colorAlgorithm;
        text: "RGB";
        anchors.left: stop.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            var algorithm = (colorMaker.algorithm() +1) % 5;
            //changetAlgorithm是上面的Javascript函式, 必須先定義,後使用
            changetAlgorithm(colorAlgorithm, algorithm);
            colorMaker.setAlgouthm(algorithm);
        }
    }

    Button {
        id: quit;
        text: "quit";
        anchors.left: colorAlgorithm.right;
        anchors.bottom: parent.bottom;
        anchors.leftMargin: 4;
        anchors.bottomMargin: 4;
        onClicked: {
            Qt.quit();
        }
    }



    Connections {
        target: colorMaker;
        onCurrentTimer: {
            timeLabel.text = strTime;
            timeLabel.color = colorMaker.timeColor;
        }
    }

    Connections {
        target: colorMaker;
        onColorChanged: {
            colorRect.color = colorMaker.color;
        }
    }


}






******************************************************************************************************************

建立的步驟如下: