我有一个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的可能性 - 也许这就是去这里的方法?
答案 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中全部是自动的,无需编写访问器,无需在每次微小更改时重新编译项目。