当前位置: 代码网 > it编程>编程语言>C/C++ > QML与C++交互之创建自定义对象的实现

QML与C++交互之创建自定义对象的实现

2025年07月07日 C/C++ 我要评论
在qml中,我们一般都是希望使用qml做界面展示,而数据处理转由c++处理;在此篇博客,将介绍如何在c++中给qml定义全局对象;在c++中如何定义对象给qml使用。1 给qml定义全局对象正常我们定

在qml中,我们一般都是希望使用qml做界面展示,而数据处理转由c++处理;

在此篇博客,将介绍如何在c++中给qml定义全局对象;在c++中如何定义对象给qml使用。

1 给qml定义全局对象

正常我们定义了一个qml项目后,main函数是这样的:

#include <qguiapplication>
#include <qqmlapplicationengine>

#include <qqmlcontext>

int main(int argc, char *argv[])
{
    qcoreapplication::setattribute(qt::aa_enablehighdpiscaling);

    qguiapplication app(argc, argv);

    qqmlapplicationengine engine;
    engine.load(qurl(qstringliteral("qrc:/main.qml")));
    if (engine.rootobjects().isempty())
        return -1;

    return app.exec();
}

qqmlapplicationengine 是 qt 框架中用于加载和运行基于 qml 的应用程序的核心类,结合了 qqmlengine 和 qqmlcomponent 的功能,支持从单个 qml 文件加载应用程序,并实现 c++ 与 qml 的双向通信。

那么,就可以使用qqmlapplicationengine去获得全局上下文对象qqmlcontext,通过使用上下文对象,就可以给qml设置一个全局的变量值;

获得上下文对象:

// 获得全局对象,上下文对象
qqmlcontext *context = engine.rootcontext();

给qml设置一个全局变量:

// 给qml设置一个全局变量;
context->setcontextproperty("screen_width", 800);

这样,就可以在qml中使用该变量了,例如在mian.qml文件内使用:

import qtquick 2.9
import qtquick.window 2.2
import qtquick.controls 2.14

window {
    id: root
    visible: true
    width: screen_width    // 直接使用
    height: 500
    title: qstr("hello world")
    color: "white"

    // 如果qml内部有定义重名变量,那么会优先使用qml内部定义的变量,而不会使用c++定义的变量
    //property int screen_width: 500
}

注意:如果qml内部有定义重名变量,那么会优先使用qml内部定义的变量;另外,定义全局变量会有性能消耗问题。

2 在c++中定义对象给qml使用

自定义c++类myobject继承自qobject;有两个成员变量,int m_ivalue 和 qstring m_sstring;并且给他俩定义get和set方法;另外在定义两个信号;最后通过q_property将两个成员变量暴露给元对象。

myobject.h

#ifndef myobject_h
#define myobject_h

#include <qobject>

class myobject : public qobject
{
    q_object

public:
    myobject(qobject *parent = nullptr);  // 构造函数
    ~myobject();

    const int &ivalue() const;
    void setiivalue(const int &newivalue);

    const qstring &sstring() const;
    void setsstring(const qstring &newsstring);

signals:
    void ivaluechanged();
    void sstringchanged();

private:
    int m_ivalue;
    qstring m_sstring;

    q_property(int ivalue read ivalue write setiivalue notify ivaluechanged)
//    q_property(qstring sstring read sstring write setsstring notify sstringchanged)
    // 如果值是函数内部成员变量的值,可使用member去设置,与read sstring write setsstring实现效果一致
    q_property(qstring sstring member m_sstring notify sstringchanged)
};

#endif // myobject_h

myobject.cpp

#include "myobject.h"


myobject::myobject(qobject *parent) : qobject(parent)
{

}

myobject::~myobject()
{

}

const int &myobject::ivalue() const
{
    return m_ivalue;
}

void myobject::setiivalue(const int &newivalue)
{
    if (m_ivalue == newivalue) {
        return;
    }

    m_ivalue = newivalue;
    emit ivaluechanged();
}

const qstring &myobject::sstring() const
{
    return m_sstring;
}

void myobject::setsstring(const qstring &newsstring)
{
    if (m_sstring == newsstring) {
        return;
    }

    m_sstring = newsstring;
    emit sstringchanged();
}

q_property的参数讲解

q_property(int ivalue read ivalue write setiivalue notify ivaluechanged)

int ivalue 指定是给qml使用的变量名,推荐与c++类成员变量名类似;

read ivalue 指的是通过ivalue函数去读取值;

write setiivalue 指的是通过setiivalue函数去修改ivalue值;

notify ivaluechanged 指的是当ivalue值被修改后,会发送的信号;

然后main函数中使用qmlregistertype函数对自定义类进行注册,注册后,就可以在qml那边导入使用了。

#include <qguiapplication>
#include <qqmlapplicationengine>

#include <qqmlcontext>
#include "myobject.h"

int main(int argc, char *argv[])
{
    qcoreapplication::setattribute(qt::aa_enablehighdpiscaling);

    qguiapplication app(argc, argv);

    qqmlapplicationengine engine;

    // 获得全局对象,上下文对象
    qqmlcontext *context = engine.rootcontext();
    // 给qml设置一个全局变量;如果qml内部有定义重名变量,那么会优先使用qml内部定义的变量;另外,定义全局变量会有性能问题
    context->setcontextproperty("screen_width", 800);

    // 注册,在需要使用的地方 import myobj 1.0
    qmlregistertype<myobject>("myobj", 1, 0, "myobject");

    engine.load(qurl(qstringliteral("qrc:/main.qml")));
    if (engine.rootobjects().isempty())
        return -1;

    return app.exec();
}

其中,myobj是给qml那边导入时使用的模块名字,1 和 0 指的是版本,最后的myobject就是自定义类名;

然后就可以在qml中 import myobj 1.0 导入使用了。

import qtquick 2.9
import qtquick.window 2.2
import qtquick.controls 2.14

import myobj 1.0    // 导入自定义模块

window {
    id: root
    visible: true
    width: screen_width
    height: 500
    title: qstr("hello world")
    color: "white"


    myobject {
        ivalue: 20
        sstring: "this is a custom obj.";

        component.oncompleted: {
            console.log("ivalue:", 20, "  sstring:", sstring)
        }
    }
}

3 番外

q_property为什么要指定notify信号呢?

在这里与qml的绑定有关系;

在qml中,当给一个变量以冒号':'方式赋值时,这两个变量是互相绑定的;例如:

property int testvalue: myobj.ivalue

当myobj.ivalue被修改时,就会触发信号通知testvalue也一并修改!

案例代码:定义变量testvalue使用冒号被myobject.ivalue赋值,定义按钮在onclicked槽函数中修改myobj.ivalue值,观察testvalue是否也被修改;

import qtquick 2.9
import qtquick.window 2.2
import qtquick.controls 2.14

import myobj 1.0    // 导入自定义模块

window {
    id: root
    visible: true
    width: screen_width
    height: 500
    title: qstr("hello world")
    color: "white"

    property int testvalue: myobj.ivalue    // 绑定了

    ontestvaluechanged: {
        console.log("testvalue:", testvalue)
    }

    button {
        width: 100; height: 50
        onclicked: {
           myobj.ivalue = 50;
        }
    }

    myobject {
        id: myobj

        ivalue: 20
        sstring: "this is a custom obj.";

        component.oncompleted: {
            console.log("ivalue:", 20, "  sstring:", sstring)
        }
    }
}

当点击按钮后,修改的是myobj.ivalue,但testvalue也一并被修改了,由此证明,使用冒号赋值时,他俩是会绑定在一起的。 

注意,使用 = 赋值时,不会有绑定的效果!!!

到此这篇关于qml与c++交互之创建自定义对象的实现的文章就介绍到这了,更多相关qml与c++交互内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com