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 那样有自动合成。

相关推荐
Greyson13 小时前
Layui表格如何使用第三方插件实现树形展示.txt
jvm·数据库·python
WBluuue3 小时前
数据结构与算法:康托展开、约瑟夫环、完美洗牌
c++·算法
2401_871696523 小时前
mysql行级锁失效的原因排查_检查查询条件与执行计划
jvm·数据库·python
Elastic 中国社区官方博客3 小时前
Elasticsearch:快速近似 ES|QL - 第一部分
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索
木子墨5163 小时前
LeetCode 热题 100 精讲 | 并查集篇:最长连续序列 · 岛屿数量 · 省份数量 · 冗余连接 · 等式方程的可满足性
数据结构·c++·算法·leetcode
Dontla4 小时前
高基数(High Cardinality)问题介绍(Prometheus、高基数字段、低基数字段)
前端·数据库·prometheus
a9511416424 小时前
CSS如何实现元素隐藏不占位_使用display-none完全移除
jvm·数据库·python
王老师青少年编程4 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌
c++·算法·编程·贪心·csp·信奥赛·均分纸牌
SelectDB技术团队5 小时前
SelectDB Enterprise 4.0.5:强化安全与治理,构建企业级实时分析与 AI 数据底座
数据库·人工智能·apache doris
一 乐5 小时前
医院挂号|基于springboot + vue医院挂号管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·医院挂号管理系统