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
     440
    height: 360
  Button
  {
     id:chineseBtn
     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
      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++就可以了,这样其实完全可以满足项大多数项目需求。 

  

原文地址:https://www.cnblogs.com/huiz/p/8120614.html