如果自定义类型是从C ++传递为const的,如何向QML注册自定义类型

时间:2018-10-12 16:38:17

标签: c++ qt qml

我有一个名为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。

1 个答案:

答案 0 :(得分:2)

您遇到的错误表明,无论如何扭曲它,它都无法与let obj = { a: 1, b: "b", c: undefined, d: null }; let cleanObj = {}; Object.keys(obj).forEach(val => { const newVal = obj[val]; cleanObj = newVal ? { ...cleanObj, [val]: newVal } : cleanObj; }); console.info(cleanObj); 一起使用,因为这不是API的设计方式,因为可以将非const对象传递给const函数,您不能做相反的事情,原因应该显而易见。而且,至少在您使用的Qt版本中,这个特定的API具有const正确的一面并没有多大意义。

直到最近,JS才真正没有常量的概念。它是在ECMA 2015中引入的,但是无论如何QML目前仍不支持该规范。 Qt 5.12会实现它,但是即使如此,我仍然怀疑它从一开始就将与C ++集成在一起。正确地传播const正确性将是一件好事,但是再一次,看到空指针变量仍然如何通过QML中的const检查,我不会屏住呼吸...

存在只读属性的概念,但实际上与常量不同,只是不能为属性分配其他值的属性,如果该值恰好是对象,则仍可以对其进行修改。

>

因此,如果要使其成为常量,最简单的操作是公开接口以对该对象进行更改。

此外,如果您对这些类型使用ifQObjectqmlRegisterUncreatableType()或类似的类型,则不需要注册qmlRegisterType()派生类型指针。 / p>

相关问题