C++和QML混合编程_C++直接调用QML函数
前言:通过QMetaObject::invokemethod()来调用QML端的函数
1、获取QML的对象(两方式可以获取,在这里踩坑半天)
2、直接通过QMetaObject::invokemethod()给对应QML对象下的函数传递参数
首先看一下目录结构:
Myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include "qdebug.h"
class Myobject : public QObject
{
Q_OBJECT
public:
explicit Myobject(QObject *parent = nullptr);
signals:
public slots:
private:
QObject *my_test_Object = nullptr;
QObject *my_test_Object_list = nullptr;
};
#endif // MYOBJECT_H
Myobject.cpp
#include "Myobject.h"
Myobject::Myobject(QObject *parent) : QObject(parent)
{
this->my_test_Object = parent;
QList<QObject *> objectList = my_test_Object->findChildren<QObject *>("mytest");
if (objectList.isEmpty()) {
qDebug() << "ColorSetting failed\n";
return;
}
qDebug() << "ColorSetting success\n";
my_test_Object_list = objectList.first();
//这个例子是直接传递三个整数型变量,并且没有返回值
QVariant res = 7;
QVariant arg_1 = 8;
QVariant arg_2 = 9;
QMetaObject::invokeMethod(my_test_Object_list, "setCSC",
Q_ARG(QVariant, res) ,
Q_ARG(QVariant, arg_1),
Q_ARG(QVariant, arg_2));
//这个例子是直接传递一个整数型变量一个字符串类型变量,有返回值
QVariant res1;
QVariant arg1_1 = 123;
QVariant arg1_2 = "zhangsan";
QMetaObject::invokeMethod(my_test_Object_list, "qmlFunc1",
Q_RETURN_ARG(QVariant, res1),
Q_ARG(QVariant, arg1_1),
Q_ARG(QVariant, arg1_2));
qDebug() << "res1 = " << res1.toString();
//这个例子是直接传递一个整数型变量一个字符串类型变量,有返回值
QVariant res2;
QVariant arg2_1 = 456;
QVariant arg2_2 = "lisi";
QMetaObject::invokeMethod(my_test_Object_list, "qmlFunc2",
Q_RETURN_ARG(QVariant, res2),
Q_ARG(QVariant, arg2_1),
Q_ARG(QVariant, arg2_2));
qDebug() << "res2 = " << res2.toInt();
}
main.cpp
注意:main.cpp中有着获取qml对象的重任,有两种方法
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "Myobject.h"
#include <QQmlComponent>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
//qmlRegisterType<Myobject>("myobj", 1, 0, "Myobject");
/***********************获取qml对象的第一种办法******************************/
--说明:这种办法是生成工程时默认自带的
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(); //自己写的用于获取qml对象
QObject *window = list.first(); //自己写的用于获取qml对象
/***********************获取qml对象的第一种办法******************************/
/***********************获取qml对象的第二种办法******************************/
--说明:这种方法一般用在自己创建的类中,尤其是在qml显示嵌套了很多层,那么对应的C++也是有很多层,这时候就用这种方法
// QQmlApplicationEngine *m_pEngine = new QQmlApplicationEngine;
// QQmlComponent component(m_pEngine, QUrl(QStringLiteral("qrc:/main.qml")));
// QObject *mainObject = component.create();
// if (mainObject == nullptr) {
// qDebug() << "mainObject fail";
// // return;
// }
/***********************获取qml对象的第二种办法******************************/
Myobject *myobj = new Myobject(window); //实例化我自己创建的类,目的是为了找到这个qml对象("mytest"),然后就可以通过QMetaObject::invokeMethod调用qml对象中的函数了
return app.exec();
}
Mytest.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
Rectangle {
objectName: "mytest"
width: 50
height: 50
color: "green"
function setCSC(luminance, contrast, saturation) { //直接被C++端调用的函数,无返回值
console.log(luminance, contrast, saturation)
}
function qmlFunc1(i, s) { //直接被C++端调用的函数,字符串返回值
console.log(i, s)
return "success"
}
function qmlFunc2(i, s) { //直接被C++端调用的函数,整数型返回值
console.log(i, s)
return 1
}
Button{
objectName: "mytest_button"
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 100
}
Text {
objectName: "mytest_text"
id: test
text: qsTr("text")
anchors.left: parent.left
anchors.leftMargin: 100
anchors.top: parent.top
anchors.topMargin: 100
}
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
Window {
id:window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Mytest{ //调用显示自己创建的qml控件
}
}