带有参数化读写访问器的Q_PROPERTY

时间:2016-02-12 11:41:55

标签: c++ qt qml

我有一个Configuration,其中包含有关文件位置的一些基本信息,例如下载,安装,图片,音乐,文档等位置。 这些目前使用Q_PROPERTY向QML公开。他们都有自己的访问者:

Q_PROPERTY(QUrl download_location READ download_location WRITE set_download_location NOTIFY download_location_changed)

这些访问器基本上都做了同样的事情,我想摆脱我必须编写的所有冗余代码。

我的第一个想法是有一个小的嵌套类FileLocation,它提供了get,set和validation函数。但是,我如何将这些连接到Q_PROPERTY

另外,如果我有一些像参数一样的静态函数(例如check_validity( QUrl location )),我将如何从QML端交出这个参数?

我认为我在这里错误的路径,所以我的问题是如何在Q_PROPERTY的上下文中将冗余代码保持在合理的限制范围内,避免写入加载和加载get,set和changed非常相似的对象的函数?

这里还有一些代码:

class Configuration : public QObject
{
  QObject

  Q_PROPERTY(QUrl download_location READ download_location WRITE set_download_location NOTIFY download_location_changed)
  Q_PROPERTY(QUrl music_location READ music_location WRITE set_music_location NOTIFY music_location_changed)
  ...

signals:
  void download_location_changed();
  void music_location_changed();
  ...

public slots:
  void set_download_location(QUrl location)
  {
    download_location = location;
    emit download_location_changed(download_location);
  }

  void set_music_location(QUrl location)
  {
    music_location = location;
    emit music_location_changed(music_location);
  }
  ...

private:
  QUrl download_location,
       music_location,
       ...;
}

因此,当你看到很多反复出现的代码也会这样做时,我希望将其降低一点。我怎么做?我正在考虑一些通用函数集,获取,更改等让成员工作的参数。但后来我还不知道如何从qml交出哪个成员。

我刚刚发现了通过qmlRegisterType(...)将C ++类暴露给qml的可能性 - 也许这就是去这里的方法?

1 个答案:

答案 0 :(得分:3)

你可以选择一个邪恶的宏:

#define IMPL(data, name) \
    inline decltype(data) name() const { return data; } \
    inline void set_##name(decltype(data) value) { if (value != data) { data = value; emit name##Changed();} }

当然,如果您不需要任何额外的东西,您只需使用MEMBER属性并让Qt自动为您生成访问者。

如果您需要在访问者中执行自定义操作,这将无法工作,宏将只需添加您的内容。

最后,当您声明Q_PROPERTY时,您可以右键单击该属性,进行重构,然后选择“生成缺少的成员...”,Qt将为访问者生成默认存根,并且您只需要添加你自定义的东西。这样做的缺点是它有一个讨厌的习惯,就是把生成的代码放在最愚蠢的地方,所以如果你希望你的课看起来整洁,你必须手动移动它。 / p>

qmlRegisterType()是你想要注册一个类型以便它可以用QML创建的,你通常不需要做任何事情来从QML访问QObject派生对象 - 它适用于{ {1}}衍生物,您只需要为没有生成元信息的类型注册元类型。

最后但并非最不重要 - 我认为将您的配置作为C ++对象没有任何意义,您也可以在QML中执行此操作,并使用Qt.labs.settings进行制作你的设置持久。 C ++仅适用于性能关键部分。如果您在QML中进行配置,则无需担心任何样板代码,因为它在QML中全部是自动的,无需编写访问器,无需在每次微小更改时重新编译项目。