0

简而言之,我想制作一个类似 JSON 的对象,QML / Qt C++ 端都可以轻松访问它。

在 QML 中,我可以制作这样的settings对象:

Item {
    id: settings
    property alias snapshot: snapshot
    QtObject {
        id: snapshot
        property string saveDirectory: "~/hello/world/"
  }
}

并使其成为单例,现在我们可以通过 settings.snapshot.saveDirectory.

但是在 C++ 中访问它非常不方便,所以我尝试在 C++ 中完成这项任务:创建一个类Settings,将实例建立为settings,然后将其QQmlApplicationEngine作为上下文传递给它。(整个应用程序只有一个实例Settings

状态.cpp

// =============================================================
/// Settings is parent

class Settings : public QObject
{
    Q_OBJECT
    Q_PROPERTY(SnapshotSettings* snapshot READ snapshot)  // <- It's pointer, very important!
public:
    explicit Settings(QObject *parent=0) : m_snapshot_settings(new SnapshotSettings) {}
private:
    SnapshotSettings* m_snapshot_settings;
}

// =============================================================
// SnapshotSettings is the child of Settings

class SnapshotSettings : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString saveDirectory READ saveDirectory)
public:
    explicit Settings(QObject *parent=0) : m_save_directory("~/hello/world/") {}
private:
    QUrl m_save_directory;
}

主文件

  1. 我注册SnapshotSettings*类型。否则,它说:

    QMetaProperty::read: Unable to handle unregistered datatype 'SnapshotSettings' for property 'Settings::snapshot'
    main.qml:52: TypeError: Cannot read property saveDirectory' of undefined
    
  2. qmlRegisterType<>() 似乎没有必要,因为我将它的实例作为上下文传递给 QML,而不是在 QML 中实例化它?

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QQmlContext>
#include "state.cpp"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);


    QQmlApplicationEngine engine;
    Settings settings;

    // ....Am I right?
    qRegisterMetaType<SnapshotSettings*>("SnapshotSettings");

    // This seems unnecessary because I use its instance as a context?
    // qmlRegisterType<Settings>("com.aisaka.taiga", 0, 1, "Settings");

    engine.rootContext()->setContextProperty("settings", &settings);
    engine.addImportPath(QStringLiteral(":/qml"));
    engine.load(QUrl("qrc:/qml/main.qml"));

    return app.exec();
}

有人告诉我,我做了一个 C++/QML 的反模式……,说“我从未见过有人这样做”。

现在看来没问题,我可以settings.snapshot.saveDirectory在 QML 中使用。但在 QtCreator 中,自动完成功能无法正常工作。saveDirectory之后不会显示settings.snapshot.

我的问题是:也许我真的做了一个反模式?如果是,有没有更好的方法来做到这一点?

谢谢。

4

1 回答 1

0

您的snapshot属性必须是 type SnapshotSettings*,即指向的指针,SnapshotSettings因为该类是 QObject 并且不能被复制。

您还应该将该属性标记为CONSTANT,因为指针永远不会改变。

saveDirectory属性要么需要一个NOTIFY信号,要么还CONSTANT取决于它是否可以在运行时更改。

于 2016-10-27T07:47:17.133 回答