Qt 注册 C++ 给 QML 调用的几种方式

1. Q_INVOKABLE / slots - 注册方法

复制代码
class MyHelper : public QObject {
    Q_OBJECT
public:
    Q_INVOKABLE QString getName() { return m_name; }
    
public slots:
    void doSomething(int value);
};

2. Q_PROPERTY - 注册属性

复制代码
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)

QML 中直接用 obj.name 访问。

3. qmlRegisterType - 注册可实例化类型

复制代码
// main.cpp
qmlRegisterType<MyClass>("MyModule", 1, 0, "MyClass");

// QML
import MyModule 1.0
MyClass { }

4. qmlRegisterSingletonType - 注册单例

复制代码
qmlRegisterSingletonType<MyApi>("MyModule", 1, 0, "MyApi", 
    [](QQmlEngine*, QJSEngine*) -> QObject* {
        return new MyApi;
    });

QML 中直接用 MyApi.method() 调用。

5. qmlRegisterUncreatableType - 注册枚举/工具类

复制代码
qmlRegisterUncreatableType<MyEnums>("MyModule", 1, 0, "MyEnums", "无法创建");

// 枚举要加 Q_ENUM
class MyEnums : public QObject {
    Q_OBJECT
public:
    enum Status { OK, Error };
    Q_ENUM(Status)
};

6. Qt 6 新语法 - QML_ELEMENT(推荐)

复制代码
// C++ 头文件
class MyHelper : public QObject {
    Q_OBJECT
    QML_ELEMENT          // 自动注册
    QML_SINGLETON        // 单例
    Q_PROPERTY(int count READ count NOTIFY countChanged)
    
    Q_INVOKABLE void refresh();
};

# CMakeLists.txt
qt6_add_qml_module(app
    URI MyModule
    VERSION 1.0
    SOURCES myhelper.h myhelper.cpp
)

对比总结:

方式 用途 Qt版本
Q_INVOKABLE 注册方法 全部
Q_PROPERTY 注册属性 全部
qmlRegisterType 可实例化类 Qt4+
qmlRegisterSingletonType 单例 Qt5+
QML_ELEMENT 自动注册(推荐) Qt6

面试回答:

"主要有三种方式:Q_INVOKABLE和slots注册方法、Q_PROPERTY注册属性、qmlRegister系列函数注册类型。Qt6推荐用QML_ELEMENT宏配合CMake自动注册,更简洁。"

READ name 里的 name 是 getter 函数名,必须自己定义

完整写法:

复制代码
class Person : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    
public:
    // READ 函数 - 必须定义
    QString name() const { return m_name; }
    
    // WRITE 函数 - 必须定义
    void setName(const QString &name) {
        if (m_name != name) {
            m_name = name;
            emit nameChanged();  // 触发信号
        }
    }
    
signals:
    // NOTIFY 信号 - 必须定义
    void nameChanged();
    
private:
    QString m_name;  // 成员变量
};

各部分说明:

部分 含义 是否必须定义
READ name getter函数名 ✅ 必须定义
WRITE setName setter函数名 ❌ 可选,只读属性不需要
NOTIFY nameChanged 值变化信号 ❌ 可选,但推荐加上

简写形式(只读属性):

复制代码
Q_PROPERTY(int count READ count CONSTANT)
// CONSTANT 表示值不变,不需要 NOTIFY

int count() const { return m_count; }

面试注意:

Qt 不会自动生成这些函数,都要手写。不像 C# 的 property 或 Kotlin 那样有自动合成。

相关推荐
刚入门的大一新生5 分钟前
Linux-简单设计libc库
linux·c++
ss2737 分钟前
Java全栈实战 | 1.3-03 索引原理:联合索引 (a,b,c) 只查 b 走不了索引?B+ 树一图讲透所有索引玄学
java·数据库
聚美智数40 分钟前
车辆合格证OCR识别-机动车合格证识别-车辆合格证OCR‑机动车出厂证解析‑整车参数提取 API 接口介绍
数据库·经验分享
DBA_G44 分钟前
南大通用技术分享:GBase 8a数据库执行计划架构原理解析
数据库
6Hzlia1 小时前
【Classic 150 刷题计划】 LeetCode 14. 最长公共前缀 | C++ 纵向扫描法与防越界细节
c++·算法·leetcode
QQ_21696290961 小时前
基于SpringBoot+Vue的小生活平台的设计与实现
java·数据库·vue.js·spring boot·spring·微信小程序·生活
考虑考虑9 小时前
数据库中的EXISTS
运维·数据库·后端
Wang's Blog9 小时前
Java框架快速入门: Spring Security+OAuth2之数据库和实体类的RBAC改造
java·数据库·spring
讳疾忌医丶9 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
2401_8685347810 小时前
OpenStack 架构全景:八个核心组件深度拆解
c++·需求分析