QML与C++几种交互方式

 更新时间:2024年04月30日 08:48:38   作者:狗蛋儿l  
QML作为构建界面的语言是非常简洁的,但是界面的后台有些时候是经常要与C++交互的,本文主要介绍了QML与C++几种交互方式,感兴趣的可以了解一下

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交互内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • C++实现LeetCode(171.求Excel表列序号)

    C++实现LeetCode(171.求Excel表列序号)

    这篇文章主要介绍了C++实现LeetCode(171.求Excel表列序号),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • N叉树的三种遍历(层次遍历、前序遍历、后序遍历)

    N叉树的三种遍历(层次遍历、前序遍历、后序遍历)

    本文主要介绍了N叉树的三种遍历(层次遍历、前序遍历、后序遍历),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • C语言 数据类型详细介绍

    C语言 数据类型详细介绍

    本文主要讲解C语言 数据类型,这里整理了详细的数据类型的资料,希望能帮助刚刚开始学习C语言的同学
    2016-08-08
  • C++编译原理之求解First集合

    C++编译原理之求解First集合

    这篇文章主要介绍的是C++/编译原理求解First集合,本文将围绕该话题详细展开全文,需要的小伙伴可以参考一下
    2021-10-10
  • 详解C++语言中的加法运算符与赋值运算符的用法

    详解C++语言中的加法运算符与赋值运算符的用法

    这篇文章主要介绍了C++语言中的加法运算符与赋值运算符的用法,是C++入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01
  • C++从文本文件读取数据到vector中的方法

    C++从文本文件读取数据到vector中的方法

    这篇文章主要给大家介绍了利用C++如何从文本文件读取数据到vector中,文章通过实例给出示例代码,相信会对大家的理解和学习很有帮助,有需要的朋友们下面来一起看看吧。
    2016-10-10
  • epoll封装reactor原理剖析示例详解

    epoll封装reactor原理剖析示例详解

    这篇文章主要为大家介绍了epoll封装reactor原理剖析示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • C++日期和时间编程小结

    C++日期和时间编程小结

    这篇文章主要介绍了C++日期和时间编程小结的相关资料,需要的朋友可以参考下
    2022-12-12
  • c++核心编程之函数的重载

    c++核心编程之函数的重载

    这篇文章主要介绍了c++核心编程之函数的重载,函数可以重复使用,提高了复用性,但前提是必须在一个作用域并且函数名称相同,下面附代码详细介绍,需要的小伙伴可以参考一下
    2022-03-03
  • C++深入讲解类与封装的概念与使用

    C++深入讲解类与封装的概念与使用

    我们都知道C++有三大特性:封装、继承、多态,现在我们来总结一下封装的相关知识与类的概念,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-04-04

最新评论