QML与C++几种交互方式
作者:狗蛋儿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交互内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!