在 C# 等语言中提供了 Property (属性)特性,对类内部的私有变量(字段)对外界提供读写方法和控制,而 C++ 没有提供这种特性。有些编译器,比如 C++ Builder 提供了 __property
关键字就是为了扩展 C++ 的这一特性。然而基于标准 C++ 编译器的 Qt 并没有这样去做。
除了使用模版、重载操作符来模拟属性的功能,通常简单地写出读、写公共函数,对私有变量进行操作。Qt 还提供了一种基于 moc (Meta-Object Compiler)的动态属性方法:QObject::property()
与 QObject::setProperty()
。使用 QObject::setProperty()
还可以方便地在运行时动态地添加和删除新的属性。看下面一个例子:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass(QObject *parent = 0);
QColor color() const {
return m_color;
}
void setColor(QColor color) {
m_color = color;
}
private:
QColor m_color;
};
...
setColor(QColor(0u));
qDebug() << color();
qDebug() << property("color");
setProperty("color", QColor(0x123456));
qDebug() << property("color");
qDebug() << color();
在例子中使用了 color()
与 setColor()
来读取和设置私有变量 m_color
的值。此外还是用了 property("color")
与 setProperty("color",QColor(0x123456))
来读取和设置 "color"
属性的值。执行的结果如下:
QColor(ARGB 1, 0.0705882, 0.203922, 0.337255)
QVariant(Invalid)
QVariant(QColor, QColor(ARGB 1, 0.396078, 0.262745, 0.129412))
QColor(ARGB 1, 0.0705882, 0.203922, 0.337255)
从结果来看这两种方法独立地将各自的属性值做了改写。我们还可以用一种方法把这两种属性联系在一起:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor)
public:
MyClass(QObject *parent = 0);
QColor color() const {
return m_color;
}
void setColor(QColor color) {
m_color = color;
}
private:
QColor m_color;
};
...
setColor(QColor(0u));
qDebug() << color();
qDebug() << property("color");
setProperty("color", QColor(0x123456));
qDebug() << property("color");
qDebug() << color();
执行结果:
QColor(ARGB 1, 0.0705882, 0.203922, 0.337255)
QVariant(QColor, QColor(ARGB 1, 0.0705882, 0.203922, 0.337255))
QVariant(QColor, QColor(ARGB 1, 0.396078, 0.262745, 0.129412))
QColor(ARGB 1, 0.396078, 0.262745, 0.129412)
可以看到,使用动态属性方法setProperty()
将私有变量 m_color
修改了。Q_PROPERTY()
宏将属性 color
、读方法 color()
、写方法 setColor()
注册到了 Meta-Object 系统中,所以再用 property()
读或用 setProperty()
去写时,不再使用默认的方法,而是用注册的方法。
Q_PROPERTY()
是一个宏定义,对于继承自 QObject 的类,可以使用 Q_PROPERTY()
宏来声明一个属性(这是由于需要用 moc 进行预编译):
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
看似有些复杂,不过对于常用到的属性的读、写方法来说还是很容易理解的:
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
enabled
是属性的名字,是一个字符串,isEnabled
是读方法,setEnabled
则是写方法。
Q_PROPERTY()
的作用还不止这些。比如,在 Qt Designer 中使用的控件有很多属性,他们是怎么定义的?明白了吧~