我什么时候应该在 Qt 上使用 qApp->setProperty

When should I use qApp->setProperty on Qt

我没有在 Qt 文档中找到解释 qApp->setProperty() 选项的部分(它可能在那里,但我找不到它).有人可以基本上向我解释它是如何工作的以及我应该什么时候使用它吗?

我问它是因为我需要将我的数据库文件的路径定义为 "global constant",以便在许多 类 中使用,所以我在考虑使用 setProperty函数。

例如:

qApp->setProperty("DATABASE_PATH", "C:/../Database.db");

然后,使用以下方式访问它:

qApp->property("DATABASE_PATH").toString();

我可以这样做还是有 better/correct 方法可以做到?

此功能在QApplication documentation的主视图中不显示。

在此页面上有一个名为:List of all members, including inherited members 的部分,您可以在其中找到您独有的或您的 parent 类.[=16= 的所有属性]

寻找这个函数建立在QObject:

bool QObject::setProperty(const char *name, const QVariant &value)

Sets the value of the object's name property to value.

If the property is defined in the class using Q_PROPERTY then true is returned on success and false otherwise. If the property is not defined using Q_PROPERTY, and therefore not listed in the meta-object, it is added as a dynamic property and false is returned.

Information about all available properties is provided through the metaObject() and dynamicPropertyNames().

Dynamic properties can be queried again using property() and can be removed by setting the property value to an invalid QVariant. Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent to be sent to the object.

Note: Dynamic properties starting with "q" are reserved for internal purposes.

See also property(), metaObject(), dynamicPropertyNames(), and QMetaProperty::write().

setProperty 用于通过其名称公开 属性,如果您可以在您的情况下使用它,因为 qApp 是一个指针,您的整个程序都可以访问它.

属性由 QObject 提供,QApplication 是 -a.

您使用的属性是所谓的动态属性,当您有一个您无法修改但需要向其添加一些额外数据的对象时非常有用。

请注意,将字符串文字传递给 propertysetProperty 是非常糟糕的风格:您很容易让拼写错误潜入。因此,属性应该只与唯一的常量名称一起使用:

// 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;
}