Qml中调用C++类的三种方式详解(一)

1.C++对象注册到元对象系统

第一步:新建一个类,QmlCpp

qmlcpp.h文件:    
#ifndef QMLCPP_H
#define QMLCPP_H
 
#include <QObject>
 
class QmlCpp : public QObject
{
    Q_OBJECT
public:
    explicit QmlCpp(QObject *parent = nullptr);
 
    Q_INVOKABLE void setValue(int nValue);
    Q_INVOKABLE int getValue();
 
signals:
 
public slots:
 
private:
    int m_nValue;
};
 
#endif // QMLCPP_H
可以看出首先使用  Q_INVOKABLE 这个宏修饰了两个成员函数。
官方文档中的描述:

Apply this macro to declarations of member functions to allow them to be invoked via the meta-object system. The macro is written before the return type

翻译:将此宏应用于成员函数的声明,以允许它们通过元对象系统被调用,宏将在返回类型之前写入。

Q_INVOKABLE这个宏是将函数申明为元对象系统可调用的函数。

QtQuick 也在元对象系统中,这样就可以在QtQuick中可以访问到这2个c++的函数了。

第二步:在main.cpp中进行注册:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "qmlcpp.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);// 在支持的平台上的Qt中启用高DPI缩放
    QGuiApplication app(argc, argv);
    
    QQmlApplicationEngine engine;
 
    QmlCpp qmlcpp;          // 先初始化一个类的实例
    qmlcpp.setValue(898);   //  设初值
    //  将这个 C++ 实例注册到 Qml 引擎上下文中标示为 “qmlpro” 的名字, 这样 Qml 中就可以通过 qmlpro 来访问这个 C++ 实例。
    engine.rootContext()->setContextProperty("qmlpro",&qmlcpp);
 
    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();
}
我们将 QmlCpp 的头文件引用进来,然后定义一个 QmlCpp 类的实例,调用设置整型的函数,并将这个 C++ 实例注册到 Qml 引擎上下文中标示为 “QmlCpp” 的名字, 这样 Qml 中就可以通过 QmlCpp 来访问这个 C++ 实例。

第三步:在Qml文件中进行调用:

import QtQuick 2.12
import QtQuick.Controls 2.12
 
Item {
 
    Button{
        id:btn
        height: 48
        width: 120
        text: "1"
        anchors.centerIn: parent
 
        onClicked: {
            text=qmlpro.getValue();
            console.log(text);
        }
    }
    Button{
        id:btn1
        height: 48
        width: 120
        anchors.top: btn.bottom
        anchors.topMargin: 12
        anchors.horizontalCenter: btn.horizontalCenter
        onClicked: {
            qmlpro.setValue(999);
        }
    }
}

其中在上述代码中,最关键的步骤是第二步,所以仔细来看一下第二步 在main.cpp中是是如何进行注册的:

 QQmlApplicationEngine engine;

首先看的是这个类 QQmlApplicationEngine,官方文档中的描述如下:
QQmlApplicationEngine提供了一种从单个QML文件加载应用程序的便捷方法。
此类结合了QQmlEngine和QQmlComponent来提供一种方便的方式来加载单个QML文件。它还向QML公开了一些中央应用程序功能,而C ++ / QML混合应用程序通常会从C ++控制这些功能。

通过官方描述得知是用来加载qml文件的。

QmlCpp qmlcpp;          // 先初始化一个类的实例
qmlcpp.setValue(898);   //  设初值
    //  将这个 C++ 实例注册到 Qml 引擎上下文中标示为 “qmlpro” 的名字, 这样 Qml 中就可以通过 qmlpro 来访问这个 C++ 实例。
    engine.rootContext()->setContextProperty("qmlpro",&qmlcpp);

接着初始化了一个实例qmlcpp,调用setValue()函数。

engine.rootContext() 返回的是一个引擎的根上下文,返回的是 QQmlContext 类型指针;
engine.rootContext()->setContextProperty(“qmlpro”,&qmlcpp);
设置根上下文 属性名为 “qmlpro”的值为 一个指针,该指针指向qmlcpp这个实例。
之后再qml中直接使用 qmlpro 调用2个公共函数。

Button{
        id:btn
        height: 48
        width: 120
        text: "1"
        anchors.centerIn: parent
 
        onClicked: {
            text= qmlpro.getValue()
        }
    }

2、补充:上述流程实现了在qml文件中调用 C++类中两个函数,这两个函数必须被Q_INVOKABLE宏进行修饰。

但是要直接访问 C++类中的属性,还需要使用到 Q_PROPERTY,

#ifndef QMLCPP_H
#define QMLCPP_H
 
#include <QObject>
#include <QJSValue>
#include <QQmlEngine>
 
class QmlCpp : public QObject
{
    Q_OBJECT
    
    // 新加的内容
    Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChange)
    
public:
    explicit QmlCpp(QObject *parent = nullptr);
 
    Q_INVOKABLE void setValue(int nValue);
    Q_INVOKABLE int getValue();
 
signals:
    //新增内容
    void valueChange();
 
public slots:
 
private:
    int m_nValue;
};
 
#endif // QMLCPP_H

C++类中新增一行代码:

Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChange)

这行代码的意思是:定义一个名称为value的属性,读取属性的函数是getValue,写入属性的函数是setValue,属性发生变化时触发的信号是valueChange。

所以在类中又新增了一个信号:

void valueChange();

然后就可以在QML文件中直接访问这个value:

Button{
        id:btn
        height: 48
        width: 120
        text: "1"
        anchors.centerIn: parent
 
        onClicked: {
            text= qmlpro.value;
        }
    }

3.qml中直接访问qmlCpp中的槽函数:

因为C++类中的槽函数本身就在元对象系统中,而我们已经把qmlCpp注册到元对象系统中,所以Qml可以直接对qmlCpp类中槽函数进行调用;

第一步:现在qmlCpp类中新建一个槽函数,addValue()

void QmlCpp::addValue(int nValue)
{    
    m_nValue += nValue;
}

在QML文件中直接调用:

  Button{
        id:btn
        height: 48
        width: 120
        text: "1"
        anchors.centerIn: parent
 
        onClicked: {
            qmlpro.addValue(10);
            text= qmlpro.value
            console.log(text)
        }
    }

总结:

至此,这篇博客讲述了如何在QML文件中访问 c++类的 成员函数、数据成员、槽函数的基本步骤。

  1. 先将自定义的C++类注册到元对象系统中。

  2. 使用Q_INVOKABLE宏修饰 类的成员函数。

  3. 使用Q_PROPERTY这个宏来定义 属性的名称 读取、写入、以及值发生变化所触发的信号。

  4. 直接调用槽函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值