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

相关推荐
IT古董7 小时前
《FDE前沿部署工程师实战教程》33 - Enterprise AI Observability:从Agent Trace到全链路智能运维
数据库·人工智能
for_ever_love__7 小时前
MySQL 主从复制讲透:binlog 原理、搭建步骤与读写分离
java·数据库·mysql·binlog·读写分离·原理·主从复制
NeilYuen10 小时前
【C++】STL源码仿写(二):vector
开发语言·c++
郝学胜_神的一滴11 小时前
游戏引擎原理与实践 04:拆解引擎基础系统与内存管理
c++·游戏
All for pursuit.11 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
weixin_3077791311 小时前
C++代码实现MATLAB中的crossval函数功能
开发语言·c++·算法·matlab
青少儿编程课堂12 小时前
背包问题(0/1 背包与完全背包)解题精讲——动态规划入门
c++·python·算法·bfs·信息学竞赛
Nturmoils12 小时前
GROUP BY 先别想当然,查汇总前把规则跑清楚
数据库
倒头就睡的小比特12 小时前
C++多态
c++
最笨的羊羊12 小时前
Oceanbase数据库系列之:向量数据库核心知识
数据库·oceanbase