如果自定义类型从 C++ 作为 const 传递,如何使用 QML 注册自定义类型
Posted
技术标签:
【中文标题】如果自定义类型从 C++ 作为 const 传递,如何使用 QML 注册自定义类型【英文标题】:How to register custom type with QML if it is passed as const from C++ 【发布时间】:2018-10-12 16:38:17 【问题描述】:我有一个名为 MyClass
的 C++ 类。该类注册为不可创建类型,因此可以在 QML 中按名称引用。
MyClass.h
:
#pragma once
#include <QObject>
class MyClass : public QObject
Q_OBJECT
public:
static void initQML();
MyClass();
MyClass(const MyClass &myClass);
~MyClass();
Q_INVOKABLE void printText();
;
MyClass.cpp
:
#include "MyClass.h"
#include <QtQml>
#include <QDebug>
#include <QMetaType>
/*static*/ void MyClass::initQML()
qmlRegisterUncreatableType<const MyClass>("Test", 1, 0, "MyClass", "Don't create it");
qRegisterMetaType<const MyClass*>("const MyClass*");
MyClass::MyClass()
qDebug() << "Constructor called.";
MyClass::MyClass(const MyClass &myClass)
qDebug() << "Copy constructor called.";
MyClass::~MyClass()
qDebug() << "Destructor called.";
void MyClass::printText()
qDebug() << "This a sample text.";
我有另一个班级,叫做MyClassFactory
。此类创建MyClass
对象。它作为单例类型注册到 QML。
MyClassFactory.h
:
#pragma once
#include "MyClass.h"
#include <QObject>
class MyClassFactory : public QObject
Q_OBJECT
public:
static void initQML();
MyClassFactory();
public slots:
static const MyClass *makeDefaultMyClass();
;
MyClassFactory.cpp
:
#include "MyClassFactory.h"
#include <QtQml>
#include <QQmlEngine>
#include <QJSEngine>
QObject *simpleQmlRegisterSingletonTypeCallback(QQmlEngine *, QJSEngine *)
return new MyClassFactory();
/*static*/ void MyClassFactory::initQML()
qmlRegisterSingletonType<MyClassFactory>("Test", 1, 0, "MyClassFactory",
simpleQmlRegisterSingletonTypeCallback);
MyClassFactory::MyClassFactory()
/*static*/ const MyClass* MyClassFactory::makeDefaultMyClass()
return new MyClass();
在我的main.qml
中,我创建了一个MyClass
类型的属性并通过MyClassFactory
将一个值绑定到它。这是我的main.qml
:
import QtQuick 2.9
import QtQuick.Controls 2.2
import Test 1.0
ApplicationWindow
visible: true
width: 480
height: 272
property MyClass myClass: MyClassFactory.makeDefaultMyClass()
Button
anchors.centerIn: parent
text: "Create MyClass"
onClicked: myClass.printText()
当我构建并运行我的代码时,我在控制台中收到以下错误:
qrc:/main.qml:12: Error: Unknown method return type: const MyClass*
如果我将const MyClass*
注册为元类型,则此错误消失,但我得到另一个错误:
qrc:/main.qml:12:31: Unable to assign const MyClass* to MyClass*
首先,如果我已经将 const MyClass
注册为 QML(不可创建)类型,为什么还要将 const MyClass*
注册为元类型?
主要问题是如何将 const 指针传递给 QML?
对于一个完整的运行示例,这是我的main.cpp
:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "MyClass.h"
#include "MyClassFactory.h"
int main(int argc, char *argv[])
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
// Init
MyClass::initQML();
MyClassFactory::initQML();
// Main loop
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
我使用 Qt 5.9.5。
【问题讨论】:
为什么不直接通过MyClass
而不是const MyClass
?
我可以通过MyClass
而不是const MyClass
,这就是我目前正在做的事情,但我想学习如何使用const
或者如果不可能做到这一点const
,那为什么?
【参考方案1】:
你得到的错误清楚地表明它不会与const
一起工作,无论如何你扭曲它,因为这不是 API 的设计方式,因为虽然你可以将非 const 对象传递给 const 函数,但你出于显而易见的原因,不能做相反的事情。而且,至少在您使用的 Qt 版本中,这个特定的 API 将具有 const 正确的一面并没有多大意义。
直到最近,JS 还没有真正意义上的常量。它是在 ECMA 2015 中引入的,但目前 QML 仍然不支持该规范。 Qt 5.12 将实现它,但即便如此,我怀疑它是否会从一开始就与 C++ 方面集成。正确传播 const 正确性将是一件好事,但话又说回来,看到空指针变体如何仍然通过 QML 中的if
检查,我不会屏住呼吸......
存在只读属性的概念,但这和常量真的不一样,只是属性不能被赋予不同的值,如果值恰好是一个对象,它仍然可以被修改。
因此,如果您希望它成为一个常量,最简单的做法是简单地不公开一个接口来对该对象进行更改。
此外,如果您对这些类型使用qmlRegisterUncreatableType()
、qmlRegisterType()
、qmlRegisterSingletonType()
或类似类型,则无需注册QObject
派生类型指针。
【讨论】:
非常感谢@dtech 的解释。我有这种感觉,但我想对此有额外的意见。 @dtech,你能看看this question我想知道你是否曾经以不同的方式解决它。以上是关于如果自定义类型从 C++ 作为 const 传递,如何使用 QML 注册自定义类型的主要内容,如果未能解决你的问题,请参考以下文章