QML与C++几种交互方式

来自:网络
时间:2024-06-09
阅读:

QML调用CPP函数

要求:

  • 使用 Q_OBJECT 宏需要继承 QObject 类。Q_OBJECT能够启用信号和槽机制、使用动态属性系统。(使用 Q_OBJECT 宏的类需要通过Qt的元对象编译器(moc)进行处理。)
  • 使用 Q_INVOKABLE 修饰要暴露给 QML 的函数。

1.在main.cpp中进行注册

 // 注册c++类到qml  参数分别为导入的 模块名称  主版本号  次版本号  模块名称
 qmlRegisterType<CppObject>("CppObject",1,0,"CppObject");

2.在qml中导入

import CppObject 1.0
 CppObject{
       id:cppobj
   }

3.通过id+方法名的方式调用

   // 加上这个宏,当前函数就可以被qml访问调用
    Q_INVOKABLE void func();
//test.h
#ifndef TEST_H
#define TEST_H

#include <QObject>
#include "QDebug"
class CppObject : public QObject
{
    Q_OBJECT
public:
    explicit CppObject(QObject *parent = nullptr);
    //通过宏定义在qml使用cpp类中的函数
    Q_INVOKABLE void print_(QString str)
    {
        qDebug()  << str;
    }

};
#endif // TEST_H
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QLocale>
#include <QTranslator>
#include "test.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QTranslator translator;
    const QStringList uiLanguages = QLocale::system().uiLanguages();
    for (const QString &locale : uiLanguages) {
        const QString baseName = "untitled_" + QLocale(locale).name();
        if (translator.load(":/i18n/" + baseName)) {
            app.installTranslator(&translator);
            break;
        }
    }

	//主要是这里其他的都是默认的
    // 注册c++类到qml  参数分别为导入的 模块名称  主版本号  次版本号  模块名称
    qmlRegisterType<CppObject>("CppObject",1,0,"CppObject");



    QQmlApplicationEngine engine;
    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.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import CppObject 1.0

Window {
    id: win
    width: 800
    height: 600
    visible: true
    title: qsTr("Hello World")

    CppObject{
            id:cppobj
        }

    Button{
            width: 50
            height: 50
            background: Rectangle{
                color:"red"
            }
            onClicked: {
                //obj.printMsg()
                cppobj.print_("test")
            }
        }

}

定义全局变量,注册到上下文

样例:

#include <QQmlContext>
QQmlApplicationEngine engine;
//这两句是重点,设置全局变量
QQmlContext *context = engine.rootContext();
context->setContextProperty("SCREEN_WIDTH", 800);

也可以用此方法将类对象暴露给QMLsetContextProperty两个参数表示的意义为:

  • 第一个参数表示 qml 可以识别的对象名
  • 第二个参数表示 C++ 对象
#include <QtQml/QQmlContext>
#include "vacUdpClient.h"
 
/*** main.cpp ***/
vacUdpClient udpclient;
QQmlContext* context = engine.rootContext();
context->setContextProperty("udpclient", &udpclient);

使用时候当变量用就行,SCREEN_WIDTH为变量名

//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QLocale>
#include <QTranslator>
//全局变量必须得头文件
#include <QQmlContext>

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QTranslator translator;
    const QStringList uiLanguages = QLocale::system().uiLanguages();
    for (const QString &locale : uiLanguages) {
        const QString baseName = "untitled_" + QLocale(locale).name();
        if (translator.load(":/i18n/" + baseName)) {
            app.installTranslator(&translator);
            break;
        }
    }

    QQmlApplicationEngine engine;
    //这两句是重点,设置全局变量
    QQmlContext *context = engine.rootContext();
    context->setContextProperty("SCREEN_WIDTH", 800);



    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.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
    id: window
    visible: true
    //使用全局变量
    width: SCREEN_WIDTH
    height: 500
    title: qsTr("Hello World")

    Button{
        width: 100
        height: 100
        background: {
            color:"black"
        }
    }
}

CPP访问QML函数

//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QLocale>
#include <QTranslator>


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QTranslator translator;
    const QStringList uiLanguages = QLocale::system().uiLanguages();
    for (const QString &locale : uiLanguages) {
        const QString baseName = "untitled_" + QLocale(locale).name();
        if (translator.load(":/i18n/" + baseName)) {
            app.installTranslator(&translator);
            break;
        }
    }

    QQmlApplicationEngine engine;
    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);


    //重点
    auto list = engine.rootObjects();
    auto window = list.first();
    QVariant res;
    QVariant arg_1 = 123;
    QVariant arg_2 = "zhangsan";
    QMetaObject::invokeMethod(window, "qmlFunc",Q_RETURN_ARG(QVariant, res),Q_ARG(QVariant, arg_1),Q_ARG(QVariant, arg_2));

    qDebug() << "res = " << res;


    return app.exec();
}

//main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15


Window {
    id: window
    visible: true
    width: SCREEN_WIDTH
    height: 500
    title: qsTr("Hello World")


    //供C++端调用的函数
    function qmlFunc(i, s) {
            return "success"
        }

   
}

单实例注册类

main.cpp文件里加这个

 // qml单实例注册
qmlRegisterSingletonInstance("PersonMudle", 1, 0, "MyPerson", &person);

以下这样使用

import PersonMudle 1.0
	Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25
 
            onClicked: {
                MyPerson.showInfo()
            }
        }

信号与槽

	//加在main.cpp中
   // engine 加载完成后 load以后
   auto list = engine.rootObjects();
   //auto objName = list.first()->objectName(); // 获取第一个objname
   //auto mybuttonObj = list.first()->findChild<QObject *>("mybutton");
   auto window = list.first();
	
	//槽函数链接
	// 第一个参数为组件
	// 第二个为信号名
	// 第三个为类的实例化
	// 第三个为槽函数
   QObject::connect(window,SIGNAL(qmlSig(int,QString)),
                    CppObject::getInstance(),SLOT(cppSlot(int,QString)));

例子:

	//类
	Person person("张三", 18);
	//上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);
 
    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clieckButton);
    */
//main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
 
 
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")
 
    Item {
        id: item
        anchors.fill: parent
 
        QtCtrl.Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)
 
            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
            }
        }
    }
 
}

到此这篇关于QML与CPP几种交互方式的文章就介绍到这了,更多相关QML CPP交互内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持! 

返回顶部
顶部