美文网首页
qml: 属性设置 Q_PROPERTY 【重点】

qml: 属性设置 Q_PROPERTY 【重点】

作者: xqiiitan | 来源:发表于2025-08-10 14:09 被阅读0次
qml属性设置,QPROPERTY.png

cpp 扩展qml类型。

//cpptype.h
#ifndef CPPTYPE_H
#define CPPTYPE_H
#include <QObject>
#include <QQmlEngine>
#include "QDebug"
class CppType : public QObject
{
    Q_OBJECT
//    QML_ELEMENT;
public:
    explicit CppType(QObject *parent = nullptr);
    Q_INVOKABLE void greet() { qDebug() << "Hello from C++!"; }

signals:
public slots:
};
#endif // CPPTYPE_H

//cpptype.cpp
#include "cpptype.h"
CppType::CppType(QObject *parent) : QObject{parent}
{
    qDebug() << "create cppType 7878";
}

#include "cpptype.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    //将自定义cpp 注册成QML组件
    qmlRegisterType<CppType>("com.example", 1, 0, "CppType");
    //...
}   
//main.qml 使用
import com.example 1.0 //导入注册的qml组件。
Window{
    id:root
    visible: true
    width: 640
    height: 480
    //cpp 扩展qml的类型。
    CppType {
        Component.onCompleted: greet()
    }
}   

2.属性设置 Q_PROPERTY 【重点】

//cpptype.h
#ifndef CPPTYPE_H
#define CPPTYPE_H
#include <QObject>
#include <QQmlEngine>
#include "QDebug"

//自定义qml组件 CppType.
class CppType : public QObject
{
    Q_OBJECT
    //属性name,可读name 可写setName.REQUIRED Qt6.2+版本才有。
    //修改属性触发信号nameChanged
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    //成员变量MENBER m_url, 声明QString类型的变量url.
    Q_PROPERTY(QString url  MEMBER m_url READ url WRITE setUrl NOTIFY urlChanged)
    // QML_ELEMENT;

public:
    explicit CppType(QObject *parent = nullptr);
    //访问cpp的方法,打印内容.
    Q_INVOKABLE void greet() { qDebug() << "Hello from C++!"; }

    //2.访问name,返回CppType设置的objectName.
    QString name() { return objectName();}
    void setName(QString name) { //内联函数,在.h中实现
        //2.1 内容修改了,才触发信号.
        if(name == objectName()) return;
        setObjectName(name);//2.2 设置新的属性
        emit nameChanged(); //2.3 手动触发信号
    }
    //getter,setter方法。
    QString url() const {return m_url;}
    void setUrl(const QString &newUrl){
        //可在此处添加url合法的验证,不合法直接return.
        if (newUrl != m_url) { //内容修改了,才触发信号.
            m_url = newUrl;
            emit urlChanged(); //发信号(信号调用)
        }
    }
    //无参,无返回值的函数.开放一个函数给qml调用.
    Q_INVOKABLE void cppFunction()
    {
        qDebug() << "call cppFunction";
        emit played(); //发送信号,触发CppType的onPlayed
    }
    //传递3种类型:基础、列表、js对象
    Q_INVOKABLE QString getData(int index,
                                std::vector<int> arr,
                                QVariantMap maps)
    {
        qDebug() << "getData index:" << index;
        for(auto v: arr) {//array
            qDebug() << v;
        }
        for(auto k: maps.keys()){//map
            qDebug() << k << ":"<<maps[k].toString();
        }
        return "getData return string";
    }

signals:
    void nameChanged(); //3.属性变化信号
    void urlChanged();
    void played(); //开始播放信号
private:
    QString m_url; //成员变量

public slots:
};
#endif // CPPTYPE_H

//cpptype.cpp

#include "cpptype.h"
CppType::CppType(QObject *parent) : QObject{parent}
{
    qDebug() << "create cppType 构造方法";
}

//main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QScreen>
#include <QApplication>
#include <QQuickView>
#include <QQmlComponent>
#include <memory>
#include <qquickwindow.h>
#include "cpptype.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    //4.将自定义cpp 注册成QML组件
    qmlRegisterType<CppType>("com.example", 1, 0, "CppType");

    QQmlEngine eng;
    QQmlComponent com(&eng);
    com.loadUrl(QUrl("qrc:/main.qml"));
    if(com.isError()) qDebug() << com.errorString();//解析代码
    //auto comwin =  static_cast<QQuickWindow*>(com.create());
    //智能指针,用完之后,ct会自动释放.
    std::unique_ptr<QQuickWindow> ct(
                static_cast<QQuickWindow*>(com.create()));
    if(com.isError()) qDebug() << com.errorString();//运行代码
    return app.exec();
}

//main.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.0
import com.example 1.0 //5.使用自定义的cpp 组件CppType

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("H1212ello World 0809 ")

    Column{
        //6.cpp 扩展qml的类型。
        CppType {
            id:cpp1
            //objectName: "abcdABCD1234"
            name: "myname"
            url: "https://www.baidu.com" //url初始值
            Component.onCompleted: greet() //调用cpp的
            onNameChanged: {
                print("onNameChanged: " + name);
            }
            onUrlChanged: {//监听URL变化,可以在这里添加 URL 验证逻辑
                print("onUrlChanged: " + url);
            }
            onPlayed: print("onPlayed---------");
        }
        Button{
            text: "cppType"
            property int count: 0
            onClicked: {
                print("onClicked: " + cpp1.name);
                cpp1.name = "newName clicked " + (count++);
            }
        }
        Button{
            text: "cppType change one."
            onClicked: {
                cpp1.name = "newName clicked!!!!";
            }
        }
        Button{
            text: "change url."
            onClicked: {
                console.log("读取url:" + cpp1.url);
                cpp1.url = "change url. 666";
            }
        }
        Button{
            property int count: 0
            text: "change url.count"
            onClicked: {
                count++;
                cpp1.url = "change url. count:" + count;//7.更新 URL 属性
                console.log("读取url:" + cpp1.url);//读取 URL 属性
            }
        }
        //------------qml: 调用cpp的函数------------
        Button{
            text: "cppFunction"
            onClicked: {
                cpp1.cppFunction();//直接调用cpp函数
            }
        }
        Button{
            text: "getData"
            onClicked: {
                var arr=[11,22,33,44]; //js数组
                //js 的对象
                var obj = {"name":"myName", "url":"myurl"};
                var res = cpp1.getData(100, arr, obj); //数据传递给cpp
                console.log(res); //打印方法的返回值
            }
        }
    }
}

qml调用c++ 扩展的函数和型号并传递数组 和js对象。

Q_INVOKABLE: 将此宏应用于成员函数的声明,以允许通过元对象系统调用它们(反射)

信号触发机制详解:

1.属性修改流程:

  • QML 修改 url 属性 → 调用 C++ setUrl() 方法
  • setUrl() 比较新旧值 → 不同则更新并触发信号
  • urlChanged() 信号触发 → QML 的 onUrlChanged 处理器执行.
    2.属性绑定示例:
Text {
    text: "当前URL: " + urlHandler.url
    // 自动绑定,url变化时自动更新
}

3.手动触发信号(如果需要)

emit urlChanged(); // 在 C++ 中
urlHandler.urlChanged()// 在 QML 中

更多:2. 添加只读属性获取 URL 各部分

//cpp
Q_PROPERTY(QString urlDomain READ urlDomain NOTIFY urlChanged)
QString urlDomain() const {
    return QUrl(m_url).host();
}
//qml
UrlHandler {
    id: handler
    // 计算属性获取 URL 协议
    readonly property string urlProtocol: {
        try {
            return url.split(":")[0]
        } catch(e) {
            return ""
        }
    }
}

相关文章

  • Qml 问答

    在Qml 文件中可以访问一个上下文C++实例的属性吗? 可以,但该属性需通过Q_PROPERTY声明 如何在Qml...

  • C++调用QML代码

    C++调用QML实际上就是通过 QML 对象的指针去访问QML对象的属性和方法 只要获取到QML对象的指针,接下来...

  • QT - QML对象属性

    QML对象属性 每个QML对象类型都有一组定义的属性。使用为该对象类型定义的属性集创建对象类型的每个实例。可以指定...

  • QML Loader 使用注意事项

    QML 的 Loader 元素经常被用来动态加载 QML 组件。可以使用 source 属性或者 sourceCo...

  • qml 附加属性

    今天看qml的例子程序,看到一个attached例子,为qml添加附加对象,这个概念有点难于理解:附加对象主要用来...

  • spring boot打包jar 文件上传 如何访问外部资源

    配置 自定义属性 设置静态资源路径 重点在于 static-locations 设置默认静态资源路径

  • QML 对象的属性

    以下内容为本人的学习笔记,如需要转载,请声明原文链接 [englyf] https://www.jianshu.c...

  • RatingBar numStars无效

    RatingBar 使用办法:使用 rating 代替numStars。重点设置 max 属性控制最大个数; s...

  • Record one usage of 'qml signal'

    ArMap.qml ArCanvas.qml

  • QML Loader使用

    能在qml组件需要的时候再创建,即延迟创建QML的时间,类似ios懒加载 main.qml page1.qml p...

网友评论

      本文标题:qml: 属性设置 Q_PROPERTY 【重点】

      本文链接:https://www.haomeiwen.com/subject/doasojtx.html