qml: 属性设置 Q_PROPERTY 【重点】

2025-08-10  本文已影响0人  xqiiitan
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.属性修改流程:

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 ""
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读