C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > QML C++交互

QML与C++几种交互方式

作者:狗蛋儿l

QML作为构建界面的语言是非常简洁的,但是界面的后台有些时候是经常要与C++交互的,本文主要介绍了QML与C++几种交互方式,感兴趣的可以了解一下

QML调用CPP函数

要求:

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两个参数表示的意义为:

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

您可能感兴趣的文章:
阅读全文