qml和cpp 交互

代码可新建项目调试通过!!!!,仔细看,好运。
1.CppObject.h

#ifndef CPPOBJECT_H
#define CPPOBJECT_H

// 参考:https://blog.csdn.net/gongjianbo1992/article/details/87965925

#include 

// 任何QML代码都可以访问QObject派生类实例的以下成员
//      属性(使用Q_PROPERTY注册的属性)
//      方法(需注册为public slots或是标记为Q_INVOKABLE)
//      信号 (看main.qml 看,76 、77行)
class CppObject : public QObject
{
    Q_OBJECT
    //注册属性,使之可以在QML中访问--具体语法百度Q_PROPERTY
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int year READ getYear WRITE setYear NOTIFY yearChanged)

public:
    explicit CppObject(QObject *parent = nullptr);
    //通过Q_INVOKABLE宏标记的public函数可以在QML中访问
    Q_INVOKABLE void sendSignal();//功能为发送信号

    //给类属性添加访问方法--myName
    Q_INVOKABLE void setName(const QString &name);
    Q_INVOKABLE QString getName() const;
    //给类属性添加访问方法--myYear
    Q_INVOKABLE void setYear(int year);

    Q_INVOKABLE int getYear() const;

signals:
    //信号可以在QML中访问
    void cppSignalA();//一个无参信号
    void cppSignalB(const QString &str,int value);//一个带参数信号
    void nameChanged(const QString name);
    void yearChanged(int year);

public slots:
    //public槽函数可以在QML中访问
    void cppSlotA();//一个无参槽函数
    void cppSlotB(const QString &str,int value);//一个带参数槽函数

private:
    //类的属性
    QString myName;
    int myYear;
};

#endif // CPPOBJECT_H

2.CppObject.cpp

#include "CppObject.h"

#include 

CppObject::CppObject(QObject *parent)
    : QObject(parent),
      myName("none"),
      myYear(0)
{

}

void CppObject::sendSignal()
{
    //测试用,调用该函数后发送信号
    qDebug()<<"CppObject::sendSignal";
    emit cppSignalA();
    emit cppSignalB(myName,myYear);
}

void CppObject::setName(const QString &name)
{
    qDebug()<<"CppObject::setName"<<name;
    if(myName!=name){
        qDebug()<<"emit nameChanged";
        myName=name;
        emit nameChanged(name);
    }
}

QString CppObject::getName() const
{
    qDebug()<<"CppObject::getName";
    return myName;
}

void CppObject::setYear(int year)
{
    qDebug()<<"CppObject::setYear"<<year;
    if(year!=myYear){
        qDebug()<<"emit yearChanged";
        myYear=year;
        emit yearChanged(myYear);
    }
}

int CppObject::getYear() const
{
    qDebug()<<"CppObject::getYear";
    return myYear;
}

void CppObject::cppSlotA()
{
    qDebug()<<"CppObject::cppSlotA";
}

void CppObject::cppSlotB(const QString &str, int value)
{
    //测试接收来自 qml 对象的信号。 信号和槽绑定在qml 组件中实现
    qDebug()<<"CppObject::cppSlotB"<<str<<value;
}

3.main

#include 
#include 

#include 
#include "CppObject.h"

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

    QGuiApplication app(argc, argv);

    // 派生自QObject的类,使用qmlRegisterType注册到QML中
    // arg1:import时模块名
    // arg2:主版本号
    // arg3:次版本号
    // arg4:QML类型名
    // 第4个参数这里有问题,类型名要和文件名一致
    // 当文件名是cppobject小写,而类名是CppObject大写,在Debug模式下无法加载成功,但Release模式下可以
    // 当类名和文件名都是大写驼峰命名CppObject,两种模式下都可以加载成功,所以最好保持文件名和类名写法一致
    qmlRegisterType<CppObject>("MyCppObject", 1, 0, "CppObject");

    QQmlApplicationEngine engine;

    //也可以注册为qml全局对象
//    engine.rootContext()->setContextProperty("cppObj",new CppObject(qApp));

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

4.qml

import QtQuick 2.9
import QtQuick.Window 2.9
//引入我们注册的模块 ,在main.cpp 21行注册
import MyCppObject 1.0

Window {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("QML和CPP 交互")
    color:"green"

    // 自定义两个信号,用来绑定到CppObject的槽函数
    signal qmlSignalA
    signal qmlSignalB(string str,int value)

    //定义一个cpp的QML对象,CppObject在main.cpp中有注册
    CppObject{
        id:cpp_obj
        //也可以像原生QML对象一样操作,增加属性之类的
        name:"china" //默认调用cpp 属性的setName方法
        year: 1949   //默认调用cpp 属性的setYear方法

        //下面是四个信号监听属性
        onCppSignalA: //这样也可以监听cpp发出的信号 ,qml对象调用了cpp的emit发射了信号,qml对象自己接受了这个信号。
        {
            show_obj_name();
        }
        onCppSignalB:
        {
            show_obj_year();
        }
        onNameChanged: {
            console.log('qml received name Changed:',cpp_obj.name); //默认调用getName方法
            console.log("--------------------------------------");
        }

        onYearChanged: {

            console.log('qml received year Changed:',cpp_obj.year)
            console.log("--------------------------------------");
        }

    }

    //鼠标点击区域
    MouseArea{
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        //测试时点击左键或右键
        onClicked: {
            if(mouse.button===Qt.LeftButton){
                console.log('----qml 点击左键:Cpp发射信号')
                //cpp_obj.name="gongjianbo"  //修改属性会触发set函数,获取值会触发get函数 ,注释掉的也可以用
                //cpp_obj.year=1995
                cpp_obj.setName("liyang");  //因为 setName 被关键字 Q_INVOKABLE 标注,所以可以访问。
                cpp_obj.setYear("1993");
                cpp_obj.sendSignal() //调用Q_INVOKABLE宏标记的函数
            }else{
                console.log('----qml 点击右键:QML发射信号')
                root.qmlSignalA()
                root.qmlSignalB('jixiaohua', 1995)
            }
        }
    }

    //组件加载完成执行
    Component.onCompleted: {
        //关联信号与信号处理函数的方式同QML中的类型
        //当cpp发出这个信号的时候,执行这个链接的方法 (qml监听cpp信号)
        cpp_obj.onCppSignalA.connect(show_obj_name)
        cpp_obj.onCppSignalB.connect(show_obj_year)

        //Qml对象的信号关联到Cpp对象的槽函数 ,(qml给cpp的槽函数发送信号)
        root.onQmlSignalA.connect(cpp_obj.cppSlotA)
        root.onQmlSignalB.connect(cpp_obj.cppSlotB)

    }

    //定义的函数可以作为槽函数,将CppObject的信号绑定到此槽函数
    function show_obj_name(str,value){

        console.log('qml function show_obj_name',cpp_obj.name)
    }
    function show_obj_year()
    {
        //当读qml的属性值时,默认调用CPP属性的getYear方法
        console.log("qml function show_obj_year: ",cpp_obj.year);
    }
    function processB(str,value)
    {

        console.log("qml function processB: ",str,value);
    }
}

你可能感兴趣的:(qml和cpp 交互)