1 QML端直接调用C++端变量及函数
1、 创建继承自QObject的C++类,对象必须继承自QObject才能在QML被使用和访问
2、在类定义中使用Q_PROPERTY导出成员的READ、WRITE、NOTIFY接口,这样类中的成员变量就可以在QML调用和修改了,同时变量被修改后也会发送信号通知QML端。用 Q_INVOKABLE 修饰成员函数,这样类中的成员函数就可以直接被QML调用。前提是该模块已经被注册过!!!
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = nullptr);
~MyObject();
static MyObject * getInstance();
//读取函数,对应READ
int getIValue();
QString getSStr();
//被 Q_INVOKABLE 修饰C++函数能直接被QML调用
Q_INVOKABLE void setCapture(bool state);
//写函数,对应 WRITE,可以没有
Q_INVOKABLE void setIValue(int value);
Q_INVOKABLE void setSStr(const QString &str);
//定义公有的槽函数
public slots:
Q_INVOKABLE void cppSlot(int i, QString s);
private slots:
void timer_timeout();
signals:
//修改通知,对应 NOTIFY,可以没有。可以分开写,也可以用同一个信号
void iValueChanged(int value);
void sStrChanged(const QString &str);
void myObjDataChanged();
void cppSig(QVariant i, QVariant s);
private:
QTimer *timer;
int iValue;
QString sStr;
// property declarations required for QML
Q_PROPERTY(int iValue READ getIValue WRITE setIValue NOTIFY myObjDataChanged)
Q_PROPERTY(QString sStr READ getSStr WRITE setSStr NOTIFY myObjDataChanged)
};
3、注册模块
QQmlApplicationEngine engine;
//1、使用setContextProperty设置全局对象/上下文对象。作用域为全局
//常用于一些不变的常量
QQmlContext *context = engine.rootContext();
context->setContextProperty("SCREEN_WIDTH", 800);
//2、使用qmlRegisterType注册模块,在qml中通过 import 模块名称 进行引用
//模块名称、主版本号、次版本号、类名称
qmlRegisterType<MyObject>("MyObj11", 1, 0, "MyObject");
4、QML端调用
//创建MyObject对象
MyObject{
objectName: "myobj"
//可直接操作MyObject类中的数据了
id: myobj
iValue: 10
sStr: "dhl"
Component.onCompleted:{
console.log(iValue, sStr)
}
}
//监控myobj.iValue的改变
onValueChanged: {
console.log("onValueChanged: ", value)
}
//1、直接访问C++的成员变量和成员函数....................................
Button{
id: btn1
objectName: "button1"
x:20; y:20
anchors.margins: 10
text: "访问C++成员和方法"
onClicked: {
myobj.iValue += 2 //修改myobj.iValue的值
onoff = onoff ? 0 : 1
myobj.setCapture(onoff) //调用C++端函数
}
}
2 QML端发送信号绑定C++端槽函数
可有两种方法可绑定QML端信号与C++端槽函数,分别在C++端绑定和在QML端绑定。需要注意的是:方式1实际是在QML信号的槽函数中调用的C++端槽函数,相当于是间接的绑定C++端的槽函数
//2、QML端发送信号绑定C++端槽函数....................................
signal qmlSig(int i, string s)
Button{
id: btn2
objectName: "button2"
x:200; y:20
anchors.margins: 10
text: "QML端发送信号绑定C++端"
onClicked: {
qmlSig(1, "qml signal--->cpp slot") //发送信号
}
}
//方式1:在QML中使用Connections连接
// Connections {
// target: root
// onQmlSig:{ //QML信号为 qmlSig(int i, string s)
// myobj.cppSlot(i, s)
// }
// }
//方式2:在QML中使用信号的connect方法
Component.onCompleted: {
qmlSig.connect(myobj.cppSlot)
}
//方式3:在C++中绑定
//详见 main.cpp
3 C++端发送信号绑定QML端槽函数
可有两种方法可绑定C++端信号与QML端槽函数,分别在C++端绑定和在QML端绑定。需要注意的是:
1、QML中槽函数的参数类型对应c++端的必须都是QVariant!!!!
2、在C++端绑定的方式,经测试,在当前版本中不好使!
//3、C++端发送信号绑定QML端槽函数....................................
function qmlSlot(i, s){ //参数类型对应c++端的必须都是QVariant!!!!
console.log("qmlslot: ", i, s)
}
//方式1:在QML中使用Connections连接
Connections{
target: myobj
onCppSig:{ //c++端信号为void cppSig(QVariant i, QVariant s),C++端发送该信号后,会执行qmlSlot函数
qmlSlot(i, s)
}
}
//方式2:在C++中绑定。经测试,此方式在当前版本中不好使!!!
//详见 main.cpp
4 C++端直接调用QML端函数
在C++端需要使用 QMetaObject::invokeMethod 方法来调用QML端函数
//4、C++端直接调用QML端函数....................................
function qmlFunc(i, s){
return "qmlFunc success"
}
//详见 main.cpp
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QVariant>
#include <QDebug>
#include "myobject.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//=====》C++与QML数据交互
//1、使用setContextProperty设置全局对象/上下文对象。作用域为全局
//常用于一些不变的常量
QQmlContext *context = engine.rootContext();
context->setContextProperty("SCREEN_WIDTH", 800);
//2、使用qmlRegisterType注册模块,在qml中通过 import 模块名称 进行引用
//模块名称、主版本号、次版本号、类名称
qmlRegisterType<MyObject>("MyObj11", 1, 0, "MyObject");
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);
//=====》C++与QML信号槽绑定
auto list = engine.rootObjects();
auto window = list.first();
// auto buttonObj = list.first()->findChild<QObject *>("button1");
//绑定qml信号与c++槽
// QObject::connect(window, SIGNAL(qmlSig(int,QString)),
// MyObject::getInstance(), SLOT(cppSlot(int,QString)));
//绑定c++信号和qml槽
// QObject::connect(MyObject::getInstance(), SIGNAL(cppSig(QVariant,QVariant)),
// window, SLOT(qmlSlot(QVariant, QVariant)));
//=====》C++直接调用QML函数
QVariant res;
QVariant arg1 = 123;
QVariant arg2 = "dhl";
QMetaObject::invokeMethod(window, "qmlFunc",
Q_RETURN_ARG(QVariant,res),
Q_ARG(QVariant, arg1),
Q_ARG(QVariant, arg2));
qDebug() <<"res=" << res;
return app.exec();
}