QML调用注册为不可创建类型的C++类函数时触发TypeError
问题原因及解决方法
核心原因
- 混淆了类型注册和实例传递的作用:
qmlRegisterUncreatableType仅用于让QML识别gui::Wallet这个类型(比如支持类型注解、信号槽关联等),但不会自动把类的实例注入到QML上下文。之前用setContextProperty是直接传递了可调用的实例,现在只注册类型的话,QML中直接调用Wallet.getSyncPercentage()本质是在调用静态方法,而你的函数是实例方法,自然报错。 - QML调用方式错误:如果没有在上下文里注入实例,直接用类型名调用实例方法,会被QML判定为类型不匹配,触发
TypeError。
解决方法
1. 结合setContextProperty传递实例
注册类型后,仍需把gui::Wallet的实例通过上下文传递给QML,两者缺一不可:
// 先注册类型 qmlRegisterUncreatableType<gui::Wallet>("com.yourdomain.wallet", 1, 0, "Wallet", "Cannot create Wallet instances in QML"); // 再传递实例到QML上下文 gui::Wallet walletInstance; engine.rootContext()->setContextProperty("wallet", &walletInstance);
之后在QML中通过注入的实例调用方法:
import com.yourdomain.wallet 1.0 // 调用实例方法 Text { text: wallet.getSyncPercentage().toString() }
2. 检查Q_INVOKABLE的声明位置
确保getSyncPercentage()在gui::Wallet类的public区域用Q_INVOKABLE标记,否则QML无法访问该方法:
class Wallet : public QObject { Q_OBJECT public: // 必须放在public下,且标记Q_INVOKABLE Q_INVOKABLE double getSyncPercentage() { // 实现逻辑 return syncPercent; } };
3. 验证类型注册的参数匹配
检查注册时的命名空间、版本号,和QML中的导入语句完全一致:
- C++注册代码的命名空间是
com.yourdomain.wallet、版本1.0,QML中必须对应写import com.yourdomain.wallet 1.0 - 注册时的类型名(第三个参数
"Wallet")要和QML中引用的类型名一致
内容的提问来源于stack exchange,提问作者user20040030
相关产品推荐
相关产品推荐

