【Qt- C++ & Qml 交互】

2024-01-07 17:17:19

■ 将C++对象注册到 QML中,在QML使用C++对象(Q_INVOKABLE宏)

在 C++ 里定义了一个对象,然后将这个对象注册到 QML 里面。在 QML 里面访问的就是 C++ 定义的对象。

■ C++对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ Q_INVOKABLE 宏

Q_INVOKABLE
Q_INVOKABLE 是个宏定义,这个宏将 函数 声明为元对象系统可调用的函数

  • Q_INVOKABLE 是个宏定义
  • 这个宏定义 针对的是 函数, 不是变量
  • 经过Q_INVOKABLE 声明过得函数 可以被元对象系统调用
  • QtQuick 也在元对象系统内,所以在 QML 中也可以访问这个被声明了的函数

■ 演示步骤

  1. 新建qml工程,里面只有一个main.cpp 与一个默认的 main.qml
  2. 创建一个C++ 的类 MyQmlClass 来与 QML 进行交互(重点关注 函数 Q_INVOKABLE宏
  3. 将 C++ 的对象,注册到 QML中去 QQmlApplicationEngine::rootContext()->setContextProperty()
  4. 做完了这两步,我们就做了 C++ 的工作,在 QML 中 就可以 直接拿到对象 myQmlImp 来调用使用 Q_INVOKABLE 定义的方法了。
  5. 改造 QML (定义一个“获取”的 Button 与 显示获取值得 Label, 点击 Button 就会获取 C++ 中的 m_value 值, 在 Lable 上进行展示。)

MyQmlClass.h

#ifndef MYQMLCLASS_H
#define MYQMLCLASS_H
 
#include <QObject> 
class MyQmlClass : public QObject
{
    Q_OBJECT
public:
    explicit MyQmlClass(QObject *parent = nullptr);
 
    Q_INVOKABLE void setValue(int value);    //这个宏将 函数 声明为元对象系统可调用的函数
    Q_INVOKABLE int getValue();   //这个宏将 函数 声明为元对象系统可调用的函数
 
signals:
 
private:
    int m_Value;
};
 
#endif // MYQMLCLASS_H

MyQmlClass.cpp

#include "MyQmlClass.h"
 
MyQmlClass::MyQmlClass(QObject *parent) : QObject(parent)
{
 
}
 
void MyQmlClass::setValue(int value)
{
    m_Value = value;
}
 
int MyQmlClass::getValue()
{
    return m_Value;
}

打开 main.cpp ,通过 QML 引擎 QQmlApplicationEngine 进行注册。

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
 
#include "MyQmlClass.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    QGuiApplication app(argc, argv); 
    QQmlApplicationEngine engine;
 
    ///
    //声明 对象  首先定义了一个C++ 的对象 myQmlImp ,
    MyQmlClass myQmlImp; 
    //将对象进行注册到QML中
    //key :自定义字符串,为了好记,我们这里叫做对象的名字 "myQmlImp"
	//value : 对象引用,对象指针,这里就是&myQmlImp
    engine.rootContext()->setContextProperty("myQmlImp", &myQmlImp);
 
    /// 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
 
    return app.exec();
}

main.qml我们的思路很简单,就是 QML 中来调用上面 C++ 暴露出来的读写函数。所以我们在QML 中定义一个 “获取” Button ,点击它我们就来调用C++中的 getValue() 函数,然后我们需要一个Label 将获取的 C++ 的值进行展示

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
 
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
 
    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空
 
        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }
 
    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度
 
        anchors.centerIn: parent   //按钮放到窗口中心
 
        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }
}

在这里插入图片描述
到这里,我们就在 QML 中获取了 C++ 代码中的值。可能到这里还有老师感觉不太真实,那么我们就继续进行验证,我们的思路是这样的:

  1. 我们增加一个 TextFiled 用于输入我们想给 。
  2. 再增加一个 “设置” 按钮,将 1中输入的值,给C++ 中的 m_Value 设值。
  3. 然后我们再点击刚才的 “获取” 按钮,将 C++ 中的 m_Value 值读取并显示出来。
    这时候我们需要对原来的QML进行改造,新增加一个输入框TextField ,进行数值输入; 还需要新增加一个“设置” 按钮,点击按钮将值赋给 C++ 中的 m_Value

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
 
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World") 
 
    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空
 
        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }
 
    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度
 
        anchors.centerIn: parent   //按钮放到窗口中心
 
        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }
 
    TextField{                      //文字输入控件
        id: textField               //唯一ID
        width: getBtn.width         //也可以直接设置成120
        height: getBtn.height       //也可以直接设置成40
 
        anchors.top: getBtn.bottom  //放到“获取”按钮下方10个像素
        anchors.topMargin: 10
        anchors.left: getBtn.left   //与“获取”按钮左对齐
    }
 
    Button{
        id: setBtn
        text: "设置"
        width: textField.width      //可以设置成getBtn.width或者120
        height: textField.height    //可以设置成getBtn.height或者40
 
        anchors.top: textField.bottom
        anchors.left: textField.left
 
        onClicked: {
            var value = textField.text
            myQmlImp.setValue(value)
        } 
    }  
}

在这里插入图片描述

■ 将C++对象注册到 QML中,在QML使用C++对象(Q_PROPERTY宏 属性绑定)

在 C++ 里定义了一个对象,然后将这个对象注册到 QML 里面。在 QML 里面访问的就是 C++ 定义的对象。

■ C++对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ Q_PROPERTY 宏

使用 Q_PROPERTY 定义交互的属性
Q_PROPERTY:用于声明属性的宏

■ 演示代码

person.h

#ifndef PERSON_H
#define PERSON_H

#include <QObject>

class Person : public QObject
{
    Q_OBJECT
    /* 使用 Q_PROPERTY 定义交互的属性 */
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)

public:
    explicit Person(QObject *parent = nullptr) : QObject(parent), m_name(""),m_age(0)
    {
    }

    /* 为属性提供 getter 和 setter 方法 */
    QString getName() const { return m_name; }
    void setName(const QString& name) { m_name = name; emit nameChanged(); }

    int getAge() const { return m_age; }
    void setAge(int age) { m_age = age; emit ageChanged(); }

   signals:
       /* 信号与属性对应,通过信号通知其他对象属性的变化 */
       void nameChanged();
       void ageChanged();

   private:
       QString m_name;
       int m_age;
};

#endif // PERSON_H

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "person.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    // 创建Person对象
    Person person;
    QQmlApplicationEngine engine;
    /* 将Person对象作为QML上下文属性 */
    engine.rootContext()->setContextProperty("person", &person);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World")

    Column {
        spacing: 10

        TextField {
            placeholderText: "请输入姓名"
            text: person.name // 与Person对象的name属性绑定
            onTextChanged: person.name = text // 当文本改变时,更新Person对象的name属性
        }

        Slider {
            from: 0
            to: 100
            value: person.age // 与Person对象的age属性绑定
            onValueChanged: person.age = value // 当滑块值改变时,更新Person对象的age属性
        }

        Text {
            text: "姓名:" + person.name
        }

        Text {
            text: "年龄:" + person.age
        }
    }
}

■ 将 C++类注册到 QML,并在QML声明一个对象并进行访问

■ C++类注册到qml中

qmlRegisterType 就是一个函数模板。将 C++ 的类型注册到 QML 系统中,并且带有版本号,方便版本管理。 我们就把main.cpp 中的函数改造一下:

■ 演示代码

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext> 
#include "MyQmlClass.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    QGuiApplication app(argc, argv); 
    QQmlApplicationEngine engine; 
//    方式一:注册定义好的对象到 QML
//    MyQmlClass myQmlImp;
//    engine.rootContext()->setContextProperty("myQmlImp", &myQmlImp);
 
//    方式二:注册类到 QML 对象
    qmlRegisterType<MyQmlClass>("com.company.myqmlclass", 1, 0, "MyQmlClass");
 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
 
    return app.exec();
}

其中:qmlRegisterType 模板函数中的 “com.company.myqmlclass” 为自定义的控件名称类似于C++中的库名称。我们在 QML 中需要 import 这个控件名, “MyQmlClass” 为 C++ 注册的类名, 1和0 为自定义版本号,方便版本管理。
在这里插入图片描述

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
import com.company.myqmlclass 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MyQmlClass{
        id: myQmlImp
    }

    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空

        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }

    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度

        anchors.centerIn: parent   //按钮放到窗口中心

        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }

    TextField{                      //文字输入控件
        id: textField               //唯一ID
        width: getBtn.width         //也可以直接设置成120
        height: getBtn.height       //也可以直接设置成40

        anchors.top: getBtn.bottom  //放到“获取”按钮下方10个像素
        anchors.topMargin: 10
        anchors.left: getBtn.left   //与“获取”按钮左对齐
    }

    Button{
        id: setBtn
        text: "设置"
        width: textField.width      //可以设置成getBtn.width或者120
        height: textField.height    //可以设置成getBtn.height或者40

        anchors.top: textField.bottom
        anchors.left: textField.left

        onClicked: {
            var value = textField.text
            myQmlImp.setValue(value)
        }
    }
}

■ 将 C++类注册到 QML,信号与槽进行交互

C++ 对象可以发出信号,而QML中的元素可以连接到这些信号上。这样,当C++ 对象的状态发生变化时,可以通过信号与槽机制将这些变化传递给QML界面。

■ C++类注册到qml中

qmlRegisterType 就是一个函数模板。将 C++ 的类型注册到 QML 系统中,并且带有版本号,方便版本管理。 我们就把main.cpp 中的函数改造一下:

■ 演示代码

myobject.h

#include <QObject>
#include <QtDebug>
 
class MyObject : public QObject
{
    Q_OBJECT 
public:
    explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} 
signals:
    void mySignal(QString message); 
public slots:
    void mySlot(const QString& message) { qDebug() << "Received message from QML:" << message; 
    	emit mySignal("Hello from C++");
    }
};

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "myobject.h"
 
int main(int argc, char *argv[])
{
    /* 启用Qt应用程序的高DPI缩放功能 */
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    /* 创建一个Qt应用程序的实例 */
    QGuiApplication app(argc, argv);
 
    /* 将自定义 C++ 类型注册到 QML 中的函数*/
    qmlRegisterType<MyObject>("com.example", 1, 0, "MyObject"); 
    
    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */
    /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    /* 加载QML文件并显示用户界面 */
    engine.load(url);
 
    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import com.example 1.0
 
Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World") 
    /* 定义 sendToCpp 信号 */
    signal sendToCpp(string message) 
    /* Connections 组件用于连接 myObject 的 onMySignal 信号 */
    Connections {
        target: myObject
        onMySignal: console.log("Received message from C++:", message)
    }
 
    MyObject {
        id: myObject
        /* 将 onMySignal 信号传递到 sendToCpp信号上,便于 QML 处理 */
        onMySignal: sendToCpp(message)
    }
 
    Button {
        text: "Send message to C++"
        anchors.centerIn: parent
        /* 单击按钮时,会将信号传递到 C++ 的 mySlot 槽上 */
        onClicked: myObject.mySlot("Hello from QML")
    }
}

■ 将C++中的数据模型注册到C++中,qml进行访问 — 模型视图

模型视图(Model-View):可以使用C++ 中的数据模型(QStandardItemModel)来提供数据给QML界面。
QML中的视图元素(如ListView或GridView)可以使用这些模型来显示数据。

■ C++数据模型对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ 演示代码

mymodel.h

#ifndef MYMODEL_H
#define MYMODEL_H
 
#include <QAbstractListModel>
#include <QList>
 
class MyModel : public QAbstractListModel
{
    Q_OBJECT 
public:
    explicit MyModel(QObject *parent = nullptr); 
    enum {
        NameRole = Qt::UserRole + 1,
        AgeRole,
        EmailRole
    };
 
    // 重写以下几个虚函数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;
 
private:
    struct Person {
        QString name;
        int age;
        QString email;
    }; 
    QList<Person> m_persons;
};
 
#endif // MYMODEL_H

mymodel.cpp

#include "mymodel.h"

MyModel::MyModel(QObject *parent)
    : QAbstractListModel(parent)
{
    // 初始化一些数据
    m_persons.append({"Alice", 25, "alice@example.com"});
    m_persons.append({"Bob", 30, "bob@example.com"});
    m_persons.append({"Charlie", 35, "charlie@example.com"});
}
int MyModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_persons.count();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (index.row() >= m_persons.count() || index.row() < 0)
        return QVariant();
    const Person &person = m_persons[index.row()];
    if (role == NameRole)
        return person.name;
    else if (role == AgeRole)
        return person.age;
    else if (role == EmailRole)
        return person.email;
    return QVariant();
}
QHash<int, QByteArray> MyModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[AgeRole] = "age";
    roles[EmailRole] = "email";
    return roles;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "mymodel.h"
 
int main(int argc, char *argv[])
{
    /* 启用Qt应用程序的高DPI缩放功能 */
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
    /* 创建一个Qt应用程序的实例 */
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
 
    MyModel myModel;
    engine.rootContext()->setContextProperty("myModel", &myModel);
 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */
    /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    /* 加载QML文件并显示用户界面 */
    engine.load(url);
 
    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
 
Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World")
 
    ListView {
        anchors.fill: parent
        model: myModel
        delegate: Item {
            width: parent.width
            height: 60
            Column {
                Text { text: name }
                Text { text: age }
                Text { text: email }
            }
        }
    }
}

在这里插入图片描述

■ C++使用QML

■ 代码演示

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2
 
Item {
    id: root
    visible: true
    width: 640
    height: 480
    //title: qsTr("Hello World")
 
    property string msg: "I am QML Item"
    signal callCpp(string arg1, string arg2)
 
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }
    }
 
    Rectangle {
        anchors.fill: parent
        color: "blue"
        objectName: "rect"
    }
 
    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("onClicked, callCpp")
            root.callCpp(root.msg, "notify cpp")
        }
    }
 
    onHeightChanged: {
        console.log("onHeightChanged execute")
    }
    onWidthChanged: {
        console.log("onWidthChanged execute")
    }
 
 
    //QML中的方法可以被cpp调用,也可以作为槽函数
    function qmlFun(val_arg) {
        console.log("qmlFun execute", val_arg, "return qmlFun_return_result")
        return "qmlFun_return_result"
    }
    //注意槽函数参数为var类型
    function invokeFromCpp(arg1, arg2) {
        console.log("invokeFromCpp execute ", arg1, arg2)
    }
}

cbusiness.h

#ifndef CBUSINESS_H
#define CBUSINESS_H
 
#include <QObject>
 
class CBusiness : public QObject
{
    Q_OBJECT
public:
    explicit CBusiness(QObject *parent = 0);
 
signals:
    void callQml(const QVariant &arg1,const QVariant &arg2);
 
public slots:
    void invokeFromQml(const QString &arg1,const QString &arg2);
};
 
#endif // CBUSINESS_H

cbusiness.cpp

#include "cbusiness.h"
 
#include <QDebug> 
CBusiness::CBusiness(QObject *parent) : QObject(parent)
{ 
} 
void CBusiness::invokeFromQml(const QString &arg1,const QString &arg2)
{
    qDebug() << "CBusiness::" << __FUNCTION__ << arg1 << arg2;
    qDebug() << "CBusiness::" << __FUNCTION__ << " emit callQml";
    emit callQml("I am cpp", "notify qml");
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QQuickView>
#include <QQuickItem>
#include <QMetaObject>
#include <QDebug>
 
#include "cbusiness.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
    QGuiApplication app(argc, argv);
 
    /*
    可以用QQmlComponent\QQuickView\QQuickWidget的C++代码加载QML文档
    当使用QQuickView时,qml的根不能是Window
    */
    QQuickView view(QUrl("qrc:/main.qml"));
    view.show();
 
    // 获取到qml根对象的指针
    QObject *qmlObj = view.rootObject();
 
 
        /*
        修改qml属性值的方法
        QObject::setProperty()  QQmlProperty  QMetaProperty::write()
        */
 
    // 通过QObject设置属性值
    qDebug() << "cpp: " << "set qml property height";
    QQmlProperty(qmlObj, "height").write(500);  //qmlObj->setProperty("height",500);
    // 通过QObject获取属性值
    qDebug() << "cpp: " << "get qml property height" << qmlObj->property("height").toDouble();
    // C++访问qml的其它属性
    qDebug() << "cpp: " << "get qml property msg" << qmlObj->property("msg").toString();
 
 
    // 获取QQuickItem
    QQuickItem *item = qobject_cast<QQuickItem*>(qmlObj);
    // 通过QQuickItem设置属性值
    qDebug() << "cpp: " << "set qml property width";
    item->setWidth(300);
    // 通过QQuickItem获取属性值
    qDebug() << "cpp: " << "get qml property width" << item->width();
 
 
    // 通过object name访问加载的QML对象
    // QObject::findChildren()可用于查找具有匹配object name属性的子项
    QObject *qmlRect = qmlObj->findChild<QObject*>("rect");
    if(qmlRect)
    {
        qDebug() << "cpp: " << "get rect color" << qmlRect->property("color");
    }
 
 
    // C++调用QML方法
    QVariant valReturn;
    QVariant valArg = "I am cpp";
    //Q_RETURN_ARG()和Q_Arg()参数必须制定为QVariant类型
    QMetaObject::invokeMethod(qmlObj, "qmlFun",
                              Q_RETURN_ARG(QVariant,valReturn),
                              Q_ARG(QVariant,valArg));
    qDebug() << "cpp: " << "QMetaObject::invokeMethod result" << valReturn.toString(); //qml函数中返回“ok”
 
 
    CBusiness cppObj;
    // cpp和qml信号与槽关联
    // qml信号绑订cpp的槽,用QString类型
    QObject::connect(qmlObj, SIGNAL(callCpp(QString, QString)), &cppObj, SLOT(invokeFromQml(QString, QString)));
 
    //关联cpp信号与qml槽
    // cpp的信号绑定qml槽,用QVariant类型
    QObject::connect(&cppObj, SIGNAL(callQml(QVariant, QVariant)), qmlObj, SLOT(invokeFromCpp(QVariant, QVariant)));
 
    return app.exec();
}

测试结果
在这里插入图片描述
信号和槽的绑定在c++代码中完成,在c++中可以修改qml的属性,获取qml的属性,调用qml的方法,传递和获取参数均可以

鼠标点击
在这里插入图片描述

文章来源:https://blog.csdn.net/sinat_23896491/article/details/135423953
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。