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

相关推荐
程序员夏末2 小时前
【MySQL | 第二篇】 MVCC的底层实现(多版本并发控制)
数据库·sql·mysql
庞轩px2 小时前
线程池核心参数与拒绝策略深度解析
java·jvm·数据库
油丶酸萝卜别吃2 小时前
MySQL 事务机制深度解析:从 ACID 到底层实现
数据库·mysql
xcLeigh2 小时前
Oracle 迁移深度复盘:多数据库选型决策全解析
大数据·数据库·sql·oracle·数据迁移·数据管理
王仲肖2 小时前
PostgreSQL pageinspect 插件深度解析
数据库·postgresql
云边有个稻草人2 小时前
【MySQL】第十四节—事务:从基础概念到隔离性理论与实践 | 详解
数据库·mysql·事务·隔离级别·事务的隔离性·事务提交方式
干啥啥不行,秃头第一名2 小时前
Python深度学习入门:TensorFlow 2.0/Keras实战
jvm·数据库·python