属性由 提供QObject
,即QApplication
-a。
您使用的属性是所谓的动态属性,当您有一个无法以其他方式修改但需要向其添加一些额外数据的对象时非常有用。
请注意,将字符串文字传递给property
or是一种非常糟糕的风格setProperty
:您很容易让拼写错误潜入。因此,属性只能与唯一的常量名称一起使用:
// common code
// proplist.h
PROPLIST_PROP(databasePath)
PROPLIST_PROP(foo)
// interface
// properties.h
#define PROPLIST_PROP(name) static const char name[];
struct Prop {
#include "proplist.h"
};
#undef PROPLIST_PROP
// implementation
// properties.cpp
#define PROPLIST_PROP(name) const char Prop::name[] = #name;
#include "proplist.h"
// use
obj.setProperty(Prop::databasePath, ...);
auto path = obj.property(Prop::databasePath).toString();
您可以封装属性的类型和名称:
// common code
// proplist.h
PROPLIST_PROP(QString, databasePath)
PROPLIST_PROP(int, foo)
// interface
#define DECLARE_PROPERTY(type_, name_) using name_ = Property<type_, struct name_>;
#define DEFINE_PROPERTY(type_, name_) const char name_::name[] = #name_;
template <typename T, typename Tag> Property {
static const char name[];
static T get(QObject * obj) {
return obj->property(name).value<T>();
}
static void set(QObject * obj, const T& val) {
obj->setProperty(name, QVariant::fromValue(val));
}
};
#define PROPLIST_PROP DECLARE_PROPERTY
namespace Prop {
#include "proplist.h"
}
#undef PROPLIST_PROP
// implementation
#define PROPLIST_PROP DEFINE_PROPERTY
namespace Prop {
#include "proplist.h"
}
// use
Prop::DatabasePath::set(obj, ...);
auto path = Prop::DatabasePath::get(obj);
我看到的主要问题是您很可能正在滥用属性系统,而可能会从全局设置对象中受益:
// interface
struct SettingsData {
SettingsData() { Q_ASSERT(!m_instance); m_instance = this; }
~SettingsData() { m_instance = nullptr; }
static SettingsData * instance() { return m_instance; }
QString databasePath = "some default value";
int gizmoSize = 44;
private:
static SettingsData * m_instance;
};
SettingsData & Settings() { return *SettingsData::instance(); }
// implementation
SettingsData * SettingsData::m_instance;
// use
int main(int argc, char ** argv) {
QApplication app(argc, argv);
SettingsData settings;
...
}
void test() {
Settings().databasePath = ...;
auto path = Settings().databasePath;
}