qml可以通过注入,导入模块,上下文等多种方式进行注入,使用场景各不相同
先看main文件,头文件中调用几个FUNC,对应几种交互方式,
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include "qml_cpp.h"
#include "qmloperation.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);
QmlOperation *MyFunc = new QmlOperation;
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);
MyFunc->Func3(engine);
MyFunc->Func2(engine);
engine.load(url);
MyFunc->Func1(engine);
return app.exec();
}
// Second, register the singleton type provider with QML by calling this function in an initialization function.
接着看cpp文件中具体的交互:头文件中几个func调用函数说明交互的方式;
头文件:
#ifndef QMLOPERATION_H
#define QMLOPERATION_H
#include <QObject>
#include <QQmlApplicationEngine>
#include "qml_cpp.h"
class QmlOperation: public QObject
{
Q_OBJECT
// qml 交互使用
Q_PROPERTY (int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged)
public:
QmlOperation();
void Func1(QQmlApplicationEngine &engine); // cpp调用qml中函数, 直接访问Q
void Func2(QQmlApplicationEngine &engine); // 注册一个单列模块
void Func3(QQmlApplicationEngine &engine); //设置上下文属性,上下文导入,zuiohao
void Func4(QQmlApplicationEngine &engine); // 注册一种类型class,struct,
Q_INVOKABLE int doSomething() { setSomeProperty(1); return index_; }
// 数据交互函数
int someProperty() const { return index_; }
void setSomeProperty(int val) { index_ = val + index_; emit somePropertyChanged(val); }
public slots:
// 槽函数
void recvSlot(int);
signals:
void somePropertyChanged(int val);
private:
int index_;
};
static QObject *exampleProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
Q_UNUSED(scriptEngine)
QmlOperation *example = new QmlOperation();
return example;
}
#endif // QMLOPERATION_H
cpp文件:
#include "qmloperation.h"
#include <QQmlContext>
#include <QDebug>
// 信号与槽函数需要的头文件:
#include <QMetaObject>
#include <QAbstractButton>
QmlOperation::QmlOperation()
{
index_ = 0;
}
void QmlOperation::Func1(QQmlApplicationEngine &engine)
{
auto root = engine.rootObjects();
// ------------------------------------------------------------------
// 调用qml中的函数
// findChild 是qml中的objectName名
auto base = root.first()->findChild<QObject *>("label1");
QVariant ret;
// 找到的返回值 函数名 函数返回值 传入参数
QMetaObject::invokeMethod(base, "getText", Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, "---------"));
qDebug() << "返回值为: " << ret.toString();
QObject *button = root.first()->findChild<QObject *>("bt1");
if (button == nullptr) {
qDebug() << " find qml objectName is err";
} else {
qDebug() << " find qml objectName is sucessed";
// QObject::connect(button,SIGNAL(clicked()),this,SLOT(recvSlot()));
QObject::connect(button,SIGNAL(bt1Signal(int)), this, SLOT(recvSlot(int)));
}
}
void QmlOperation::Func2(QQmlApplicationEngine &engine)
{
// 注册一个接口,叫 MyApi_Func2
qmlRegisterSingletonType<QmlOperation>("Qt.example.qobjectSingleton", 1, 0, "MyApi_Func2", exampleProvider);
}
void QmlOperation::Func3(QQmlApplicationEngine &engine)
{
// 传入的数据或者类都是全局的,一般不建议使用,但是目前很多代码中都是大量使用
qml_cpp *data = new qml_cpp;
QQmlContext * con = engine.rootContext();
con->setContextProperty("dataApi", data);
int maxData = 99;
con->setContextProperty("myIndex", maxData);
}
void QmlOperation::Func4(QQmlApplicationEngine &engine)
{
// 注入 qml_cpp 这个类
qmlRegisterType<qml_cpp>("modelData", 1, 0, "myData");
}
void QmlOperation::recvSlot(int key)
{
qDebug() << " qml button is clicked return value is: "<< key;
}
一个作为纯数据交换的文件:
class qml_cpp : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
explicit qml_cpp(QObject *parent = nullptr);
Q_INVOKABLE void prinfData() const noexcept;
signals:
Q_INVOKABLE void cppSend() const;
Q_INVOKABLE void CppSendString(QString) const;
private:
QString str_;
int cppIndex;
signals:
};
//---------------------------------------------------------
qml_cpp::qml_cpp(QObject *parent) : QObject(parent)
{
str_ = " this is cpp string data";
}
void qml_cpp::prinfData() const noexcept
{
qDebug() << " this is cpp func ----------------------------------------------------- printfData";
emit cppSend();
emit CppSendString("this is cpp signal");
}
最后是qml文件,三个按钮对应不同的交互方式:
import QtQuick 2.0
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
import QtQml 2.12
import './test.js' as MyFunc // 导入js文件, as 别名
import Qt.example.qobjectSingleton 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ColumnLayout{
anchors.fill: parent
RowLayout {
// anchors.horizontalCenter: parent.horizontalCenter
// Layout.preferredWidth: parent.width
// Layout.preferredHeight: 130
Label {
objectName: "label1"
text: " 这是cpp调用qml 中的函数"
function getText(str) { // cpp调用qml中的函数
return text + str
}
}
Button {
signal bt1Signal(int index) // 自定义一个信号
objectName: "bt1"
text: "Func1"
onClicked: {
bt1Signal(999)
}
}
}
RowLayout {
Label {objectName: "label2"; text: " this is label"}
Button {
// func 2
property int someValue: MyApi_Func2.someProperty
onSomeValueChanged: {
console.log("func2 someValue is changeed, value is : ", someValue)
}
// Layout.alignment: Qt.AlignCenter
objectName: "bt2"
text: "Func2"
onClicked: {
MyApi_Func2.doSomething(); // 调用 cpp中的 doSomething,使value
}
}
}
RowLayout {
Label {objectName: "label3"; text: " 这是 qml调用cpp内部函数"}
Button {
objectName: "bt3"
text: "Func3"
onClicked: {
dataApi.prinfData();
// console.log("cpp传入全局变量 myIndex: ", myIndex)
}
Connections {
target: dataApi
function onCppSend() {
console.log("this is cpp signal, argument is: ");
}
}
}
}
}
}