一、全局属性

在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__<<"  "<

3.在main.cpp中访问 定义这个复杂的类型

有两种方式

#include #include #include #include #include #include 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("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("btnClick");    // qDebug()<

///     return app.exec(); }

4.在qml中访问

需要导入对象名和主次版本号 ,才能正式使用

import HelloMyObj 1.0

import QtQuick 2.14 import QtQuick.Window 2.14 import QtQuick.Controls 2.12

import HelloMyObj 1.0

Window {     id: window

    property int value: myobj.ivalue    visible: true     width: 640     height: 480     title: qsTr("hello")

  MyObject{        id: myobj

       iValue: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__<<" "<

}

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("btnClick");

// qDebug()<

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 = "<

3.在qml中调用c++中的函数

3.1在myobject.h中定义

//定义一个函数 加Q_INVOKABLE 就可以让qml访问

Q_INVOKABLE void func();

3.2在qml中使用

Button {

objectName: "btnClick"

onClicked: {

MyObject.func()

}

}

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: