C++和QML聯合編程


  項目用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++就可以了,這樣其實完全可以滿足項大多數項目需求。 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM