一、全局属性
在main.cpp中通过 QQmlApplicationEngine engine 获得全局对象
QQmlApplicationEngine engine;
//全局对象 上下文对象
QQmlContext* context = engine.rootContext();
//获取屏幕的大小
Screen *screen= QGuiApplication::primaryScreen();
QRect rect= screen->virtualGeometry(); //整个屏幕的大小
//注册的上下文对象 它是作用于全局 有重命名的风险
context->setContextProperty("SCREEN_WIDTH",rect.width()/2); //设置全局属性 所有QMl文件都能访问得到的
在qml中使用 SCREEN_WIDTH 全局属性
width: SCREEN_WIDTH //screen.desktopAvailableWidth 获取整个屏幕的宽度
二,创建自定义对象,在QMl中使用
1.创建一个MyObject类
2.在myobject.h中定义一些属性,以便在qml中可以使用 并为每个属性添加读写的方法和相应的信号
class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = nullptr); int iValue() const; void setIValue(int iValue); QString sString() const; void setSString(const QString &sString); //定义一个函数 加Q_INVOKABLE 就可以让qml访问 Q_INVOKABLE void func(); private: //生成get 和set 方法 int m_iValue; QString m_sString; //宏 //第一种方式 //声明一个名称 int iValue 想是QMl 中width //READ iValue --->通过那个函数读的 // WRITE setIValue---》通过那个函数写的 //NOTIFY iValueChanged 当前这个值修改会发出iValueChanged信号 /* Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged) Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)*/ //第二种方式 Q_PROPERTY(int iValue MEMBER m_iValue NOTIFY iValueChanged) Q_PROPERTY(QString sString MEMBER m_sString NOTIFY sStringChanged) public slots: //槽函数 void ccpSlot(int i,QString str); signals: void iValueChanged(); void sStringChanged(); //定义一个信号,在qml中绑定槽函数 void cppSig(QVariant i,QVariant s); };
2.在myobject.cpp中实现
#include "myobject.h"
MyObject::MyObject(QObject *parent) : QObject(parent)
{}
MyObject *MyObject::getInstance()
{
static MyObject * obj = new MyObject();
return obj;
}int MyObject::iValue() const
{
return m_iValue;
}void MyObject::setIValue(int iValue)
{
if(m_iValue == iValue)
return;m_iValue = iValue;
//发出信号
emit iValueChanged();
}QString MyObject::sString() const
{
return m_sString;
}void MyObject::setSString(const QString &sString)
{
if(m_sString == sString)
return;
m_sString = sString;
emit sStringChanged();
}void MyObject::func()
{
emit cppSig(101,"王五"); //发送信号
qDebug()<<__FUNCTION__;//当前函数名称}
void MyObject::ccpSlot(int i, QString str)
{
qDebug()<<__FUNCTION__<<" "<<i<<" "<<str;
}
3.在main.cpp中访问 定义这个复杂的类型
有两种方式
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QScreen>
#include <myobject.h>
#include <QObject>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//
//全局对象 上下文对象
QQmlContext* context = engine.rootContext();//获取屏幕的大小
QScreen *screen= QGuiApplication::primaryScreen();
QRect rect= screen->virtualGeometry(); //整个屏幕的大小
//注册的上下文对象 它是作用于全局 有重命名的风险
context->setContextProperty("SCREEN_WIDTH",rect.width()/2); //设置全局属性 所有QMl文件都能访问得到的
//qml中就可以访问这个对象myObjectOO
//但是qml 并不能认识这个这个复杂的类型//方式一
//context->setContextProperty("myObjectOO",MyObject::getInstance());//一般不用这个方法//方式二
//四个参数
//第一个参数是qml中导入的名称 import HelloMyObj 1.0
//第二个第三个参数分别是主次版本号;第四个指的是QML中类的名字。
//qmlRegisterType<MyObject>("HelloMyObj",1,0,"MyObject");
//我们一定要通过创建对象来定义一个我们自定义的object//创建一个全局的单例的模式
qmlRegisterSingletonInstance("HelloMyObj",1,0,"MyObject",MyObject::getInstance());
///
//地址
const QUrl url(QStringLiteral("qrc:/CPPSlotSignal.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中发出的信号
//engine 加载完成后 load以后
auto list = engine.rootObjects(); //返回CPPSlotSignal.qml 中所有的对象
//auto objectName = list.first()->objectName();
// auto btnName = list.first()->findChild<QObject *>("btnClick");
// qDebug()<<btnName;
auto window = list.first();
//绑定
QObject::connect(window,SIGNAL(qmlSig(int,QString)),
MyObject::getInstance(),SLOT(ccpSlot(int,QString)));
//绑定
QObject::connect(MyObject::getInstance(),SIGNAL(cppSig(QVariant,QVariant)),
window,SLOT(qmlSlot(QVariant,QVariant)));///
return app.exec();
}
4.在qml中访问
需要导入对象名和主次版本号 ,才能正式使用
import HelloMyObj 1.0
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.12import HelloMyObj 1.0
Window {
id: windowproperty int value: myobj.ivalue
visible: true
width: 640
height: 480
title: qsTr("hello")
MyObject{
id: myobjiValue:20
sString:"hello"
}onValueChanged:
{
console.log(value)
}
Button{
onClicked: {
myobj.iValue = 20
}
}
三、QML端发送信号,绑定c++端的函数
1.在qml写好信号,并发出
Window { id: window objectName: "window" visible: true width: 640 height: 480 title: qsTr("QML端发送信号,绑定c++端的函数") //信号 signal qmlSig(int i,string s) Button { objectName: "btnClick" onClicked: { //发送信号 qmlSig(22,"hello") } }
2.在类中定义槽函数
public slots:
//槽函数
void ccpSlot(int i,QString str);
实现
void MyObject::ccpSlot(int i, QString str)
{
qDebug()<<__FUNCTION__<<" "<<i<<" "<<str;
}
3.绑定信号与槽函数
3.1在main.cpp绑定----C++端绑定qml中发出的信号
//engine 加载完成后 load以后
auto list = engine.rootObjects(); //返回CPPSlotSignal.qml 中所有的对象
//auto objectName = list.first()->objectName();
// auto btnName = list.first()->findChild<QObject *>("btnClick");
// qDebug()<<btnName;
auto window = list.first();
//绑定
QObject::connect(window,SIGNAL(qmlSig(int,QString)), MyObject::getInstance(),SLOT(ccpSlot(int,QString)));
3.2在qml端绑定C++类的槽函数 两种方式
MyObject{
id: myobj
}
//连接C++中槽函数
//1.
/*Connections{
target: window //发出者
function onQmlSig(i,str){
myobj.ccpSlot(i,str)
}
}
*/
//2.在组件完成时与连接
/* Component.onCompleted: {
qmlSig.connect(myobj.ccpSlot)
} */
四、c++端发出信号,qml端绑定槽函数
1.myobject.h的定义信号
//定义一个信号,在qml中绑定槽函数
void cppSig(QVariant i,QVariant s);
2.在qml中定义槽函数
function qmlSlot(i,s){ // 参数类型 对应CPP端 都是QVariant console.log("qml",i,s)
}
3.绑定
3.1c++端绑定
auto list = engine.rootObjects();
auto window = list.first(); QObject::connect(MyObject::getInstance(),SIGNAL(cppSig(QVariant,QVariant)), window,SLOT(qmlSlot(QVariant,QVariant)));
3.2qml端绑定
Connections{
target: MyObject //发出者
function onCppSig(i,str){
qmlSlot(i,str)
}
4.可以不用在qml实现MyObject 对象,只需要在main中创建一个全局的单例的模式
qmlRegisterSingletonInstance("HelloMyObj",1,0,"MyObject",MyObject::getInstance());
五、C++端直接调用QML函数
1.qml中写函数
function qmlFunc(i,s){
return " are you ok?"
}
2.在main.cpp中调用
auto list = engine.rootObjects(); //返回CPPSlotSignal.qml 中所有的对象
auto window = list.first();
//调用QML端的函数
//第一参数,拥有者 第二参数 函数名称 第三参数 保存到哪 后面就是要传递的参数
QVariant resFunc;
QVariant arg_1 = 123;
QVariant arg_2 = "I am fine ";
QMetaObject::invokeMethod(window,"qmlFunc", Q_RETURN_ARG(QVariant,resFunc), Q_ARG(QVariant,arg_1),
Q_ARG(QVariant,arg_2));
qDebug()<<"res = "<<resFunc;
3.在qml中调用c++中的函数
3.1在myobject.h中定义
//定义一个函数 加Q_INVOKABLE 就可以让qml访问 Q_INVOKABLE void func();
3.2在qml中使用
Button {
objectName: "btnClick"
onClicked: {
MyObject.func()
}
}