首页 > 解决方案 > 如何将值对象的工厂暴露给 QML?

问题描述

我想制作没有默认构造函数和设置器的值对象,可以从 QML 创建。我将 Factory 的实现作为解决方法,它将像单例一样传递给 QML。但是当我尝试使用它时,我得到“错误:未知方法返回类型:点”,当我关闭应用程序崩溃时,日志中出现“free():无效指针”消息。

点.h:

#ifndef POINT_H
#define POINT_H

#include <QObject>

struct Point
{
    Q_GADGET
    Q_PROPERTY(int x READ getX CONSTANT)
    Q_PROPERTY(int y READ getY CONSTANT)

public:
    Point(int x, int y) : x(x), y(y) {

    }

    Point(const Point& that) = default;
    Point& operator=(const Point& that) = default;

    int getX() {
        return this->x;
    }

    int getY() {
        return this->y;
    }

    Q_INVOKABLE QString getCoordinates() {
        return QString("x=%1; y=%2").arg(this->x, this->y);
    }

private:
    int x;
    int y;
};

#endif // POINT_H

工厂.h:

#ifndef FACTORY_H
#define FACTORY_H

#include <QObject>

#include "point.h"

class Factory : public QObject {
    Q_OBJECT
    Q_DISABLE_COPY(Factory)

public:
    static Factory* instance() {
        static Factory factory;
        return &factory;
    }

    Q_INVOKABLE Point newPoint(int x, int y) {
        return Point(x, y);
    }

private:
    Factory() {

    }
};

#endif // FACTORY_H

主.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>

#include "factory.h"
#include "point.h"


int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterUncreatableType<Point>("test", 1, 0, "Point", "error: no default constructor");
    qmlRegisterSingletonType<Factory>("test", 1, 0, "Factory",
                                      [](QQmlEngine* engine, QJSEngine* scriptEngine) -> QObject* {
        Q_UNUSED(engine)
        Q_UNUSED(scriptEngine)

        return Factory::instance();
    });

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml:

import QtQuick 2.9
import QtQuick.Controls 2.3

import test 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Component.onCompleted: {
        var point = Factory.newPoint(5, 10);
        console.log("completed")
    }
}

标签: c++qtqml

解决方案


推荐阅读