【问题标题】:How to make a JSON-like QObject如何制作类似 JSON 的 QObject
【发布时间】:2016-10-27 02:46:43
【问题描述】:

简而言之,我想制作一个类似 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的实例)

state.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;
}

main.cpp

  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&lt;&gt;() 似乎没有必要,因为我将它的实例作为上下文传递给 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 的反模式……,说“我从来没有见过有人这样做”。

现在似乎好了,我可以在 QML 中使用settings.snapshot.saveDirectory。但在 QtCreator 中,自动完成功能无法正常工作。saveDirectorysettings.snapshot. 之后不会显示)

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

谢谢。

【问题讨论】:

  • 这是什么意思 - 自动完成工作不正确?
  • @folibis saveDirectory 在输入 settings.snapshot. 后不会显示

标签: qt qml qt-creator moc qproperty


【解决方案1】:

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

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

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

【讨论】:

  • 1.对不起,这是一个错字。我确实用过Q_PROPERTY(SnapshotSettings* ...),问的时候忘记加了。
  • 2.我不需要它的NOTIFY,所以它被省略了。
  • 虽然没有NOTIFY 的属性实际上是恒定的,就像没有重新评估一样,但不明确说明这一点是不好的形式,QML 引擎会在运行时抱怨这一点。不过一般的方法很好。顺便说一句,“~”是主目录的 shell 快捷方式,它在 URL 中的含义不一定相同。更好的用户 QUrl::fromLocalFile() 为本地路径创建 URL
猜你喜欢
  • 2015-08-22
  • 2010-12-19
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多