Qt属性系统
2016-02-01 19:54
375 查看
ThePropertySystem
Qt提供一个类似于其他编译器供应商提供的精致的属性系统。然而,作为一个编译器和平台独立的库,Qt并不依赖于非标准编译器特性,如__property或[property]。Qt解决方案能在支持Qt的平台上与任何标准C++编译器一起工作。它依赖于Meta-ObjectSystem。
Q_PROPERTY()宏。
Q_PROPERTY(typename
READgetFunction
[WRITEsetFunction]
[RESETresetFunction]
[NOTIFYnotifySignal]
[REVISIONint]
[DESIGNABLEbool]
[SCRIPTABLEbool]
[STOREDbool]
[USERbool]
[CONSTANT]
[FINAL])
以下是摘自QWidget类的典型的属性声明:
属性的行为跟数据成员一样,但是它有通过Meta-ObjectSystem.的额外特性。
·需要有READ函数.用来读取属性的值.理想的,为此最好是const函数,必须返回属性的类型或者属性类型一个指针或引用,QWidget::focus是只读属性,读取函数QWidget::hasFocus().
·WRITE函数是可选的.它用来设置属性值.。它必须返回void和带一个参数,参数为属性的类型或者类型的引用或指针。如QWidget::enabled有一个WRITE函数QWidget::setEnabled().。只读属性不需要有WRITE函数,如QWidget::focus没有WRITE函数。
·RESET函数也是可选的。它用来设置属性值为上下文指定的默认值。QWidget::cursor有典型的READ和WRITE函数,QWidget::cursor()和QWidget::setCursor(),并且它有RESET函数,QWidget::unsetCursor(),。因为没有调用QWidget::setCursor()可以设置,上下文指定的光标。RESET函数必须返回void和不带参数。
·NOTIFY信号是可选的。如果定义,它指定为类中已经存在的信号,如果属性值发生变化则发出该信号。
·REVISION数是可选的。如果包含,它定义了属性和它的通知信号,被用在特定的公开给QML的API版本。
·DESIGNABLE属性指明在属性编辑的GUI设计工具是否可见。大多数属性是DESIGNABLE(默认true),取代true或false,你可以指定一个布尔成员函数。
·SCRIPTABLE属性指示脚本引擎是否可以访问该属性(默认true)。取代true或false,你可以指定一个布尔成员函数。
·STORED属性指示属性是否应该认为是自身有的还是依赖于其他值的,也指明了当存储对象的状态是必须保存属性值。大部分的属性是STORED(默认true),但是QWidget::minimumWidth()的STORED是false,因为它的值是从属性QWidget::minimumSize(),取得的。
USER属性指示属性是否认定为面向用户或用户可用编辑的。通常,每个类只有一个USER属性,如对于按钮QAbstractButton::checked是用户可编辑的属性。注意:QItemDelegate获取和设置widget的USER属性。
·CONSTANT属性指明属性值是常量。对于给定的对象实例,READ函数每次调用返回的值是一样的。不同的对象实例的常量值可能不一样,常量属性不能有WRITE函数NOTIFY信号。
FINAL属性指明.属性不能被子类重写。在某些情况下可以用于性能优化,但是moc并不强制进行。小心不能重写FINAL属性。
READ,WRITE,和RESET函数可以被继承,也可以是虚函数。如果是在多继承的类,它们必须是来自第一个被继承的类。
属性类型是QVariant支持的任意类型,也可以是用户自定义类型。在这个例子中,QDate类被当成是自定义类型。
由于QDate是用户自定义的,在声明属性时必须包含头文件<QDate>。
对于QMap,QList,和QValueList属性,属性的值是一个包含整个list或map的QVariant。注意:Q_PROPERTY字符串不能包含逗号,因为逗号分割了宏参数。因此,你必须用Qmap替代QMap<QString,QVariant>做属性类型。一致的,用QList和QvalueList取代QList<QVariant>和QValueList<QVariant>.。
QObject::property()和QObject::setProperty(),来读写属性。除了属性的名称以为不用知道类的其他信息。下面的代码段,调用QAbstractButton::setDown()和QObject::setProperty()都是设置"down"属性。
用WRITE函数访问属性是最好的,因为.它更快而且编译时更好判断,但是用这种方法设置属性你需要知道运行时中的类。通过属性名称访问属性使你可以访问在运行时不知道的类。你可以通过查询它的QObject,QMetaObject,和QMetaProperties.获取类在运行时的属性。
在以上代码,QMetaObject::property()用来获取位置类中定义的每个属性的元数据。从元数据中获取属性名并传给QObject::property()以获得当前对象的该属性的值。
QObject并在private段声明了Q_OBJECT宏。我们想在MyClass中声明一个属性来跟着一个优先级值。属性名为priority,它的类型为在MyClass定义的枚举Priority,类型。
我们用Q_PROPERTY()宏在private段声明该属性,READ函数为priority,WRITE函数为setPriority.。枚举类型必须用Q_ENUMS()宏进行注册。注册一个枚举类型使得枚举类型名对于QObject::setProperty().调用是有效的。我们必须为READandWRITE函数提供自己的声明。MyClass的声明可能如下:
READ函数是const并且返回属性的类型,WRITE返回void并带有属性类型的一个参数。元对象编译器执行这些要求。
给定一个指向MyClass对象的指针或者一个指向MyClass实例的QObject指针,我们有两种方法设置它的属性:
在例子中,在MyClass中定义并用Q_ENUMS()注册的枚举类型是属性的类型,这使得枚举值在setProperty()调用中是有效的字符串。如果枚举类型在另外的类中声明,则需要它的完全限定名,而且那个类必须继承QObject和用Q_ENUMS()宏注册枚举类型。
一个类似的宏,Q_FLAGS(),。跟Q_ENUMS(),宏一样,它注册一个枚举类型,但是它标记类型为一组标记,值可以用OR操作。一个IO类可能有Read和Write枚举值,QObject::setProperty()可以接收Read|Write.。应该用Q_FLAGS()注册该枚举值。
QObject::setProperty()也可以用来为运行时的类实例添加新的属性。当用一个name和value调用该函数,如果给定的name属性存在于QObject,中而且给定的value值与属性的类型兼容,则value被存储到属性中并返回true。如果value和属性的类型不兼容,属性的值不变并返回false。但是如果给定的name属性不存在于QObject中,则新的属性name和值value被自动添加到QObject,但是依旧返回false。这意味着返回false不能用来确定特定的属性是否被设置,除非你事先知道属性存在于QObject。
注意:dynamic属性被添加到每个实例的根,它们被添加到QObject而不是QMetaObject.。通过该QObject::setProperty()传一个属性名和非法的QVariant值可以掉一个实例属性。QVariant的默认构造函数构造一个非法的值。
和Q_PROPERTY()声明的属性一样,Dynamic属性可以用QObject::property(),进行查询。
Q_DECLARE_METATYPE()宏注册以使自定义类型的值可以存储在一个QVariant对象中。这使得它们适合用于Q_PROPERTY()宏声明的静态属性和运行时创建的属性。
Q_CLASSINFO()是连接到属性系统的额外的宏,它可以添加额外的name--value信息到类的元数据,如:
和其他元数据一样,类信息也可以通过运行时的元数据对象获取。
http://blog.csdn.net/hai200501019/article/details/9204215
Qt提供一个类似于其他编译器供应商提供的精致的属性系统。然而,作为一个编译器和平台独立的库,Qt并不依赖于非标准编译器特性,如__property或[property]。Qt解决方案能在支持Qt的平台上与任何标准C++编译器一起工作。它依赖于
RequirementsforDeclaringProperties
要声明一个属性,在继承Qobject的类中用READgetFunction
[WRITEsetFunction]
[RESETresetFunction]
[NOTIFYnotifySignal]
[REVISIONint]
[DESIGNABLEbool]
[SCRIPTABLEbool]
[STOREDbool]
[USERbool]
[CONSTANT]
[FINAL])
以下是摘自
Q_PROPERTY(boolfocusREADhasFocus)
Q_PROPERTY(boolenabledREADisEnabledWRITEsetEnabled)
Q_PROPERTY( QCursor cursorREADcursorWRITEsetCursorRESETunsetCursor)
属性的行为跟数据成员一样,但是它有通过
·需要有READ函数.用来读取属性的值.理想的,为此最好是const函数,必须返回属性的类型或者属性类型一个指针或引用,
·WRITE函数是可选的.它用来设置属性值.。它必须返回void和带一个参数,参数为属性的类型或者类型的引用或指针。如
·RESET函数也是可选的。它用来设置属性值为上下文指定的默认值。
·NOTIFY信号是可选的。如果定义,它指定为类中已经存在的信号,如果属性值发生变化则发出该信号。
·REVISION数是可选的。如果包含,它定义了属性和它的通知信号,被用在特定的公开给QML的API版本。
·DESIGNABLE属性指明在属性编辑的GUI设计工具是否可见。大多数属性是DESIGNABLE(默认true),取代true或false,你可以指定一个布尔成员函数。
·SCRIPTABLE属性指示脚本引擎是否可以访问该属性(默认true)。取代true或false,你可以指定一个布尔成员函数。
·STORED属性指示属性是否应该认为是自身有的还是依赖于其他值的,也指明了当存储对象的状态是必须保存属性值。大部分的属性是STORED(默认true),但是
USER属性指示属性是否认定为面向用户或用户可用编辑的。通常,每个类只有一个USER属性,如对于按钮
·CONSTANT属性指明属性值是常量。对于给定的对象实例,READ函数每次调用返回的值是一样的。不同的对象实例的常量值可能不一样,常量属性不能有WRITE函数NOTIFY信号。
FINAL属性指明.属性不能被子类重写。在某些情况下可以用于性能优化,但是moc并不强制进行。小心不能重写FINAL属性。
READ,WRITE,和RESET函数可以被继承,也可以是虚函数。如果是在多继承的类,它们必须是来自第一个被继承的类。
属性类型是
Q_PROPERTY( QDate dateREADgetDateWRITEsetDate)
由于
对于
ReadingandWritingPropertieswiththeMeta-ObjectSystem
可以用同用的函数QPushButton *button=newQPushButton ;
QObject *object=button;
button->setDown(true);
object->setProperty("down",true);
用WRITE函数访问属性是最好的,因为.它更快而且编译时更好判断,但是用这种方法设置属性你需要知道运行时中的类。通过属性名称访问属性使你可以访问在运行时不知道的类。你可以通过查询它的
QObject *object=...
constQMetaObject *metaobject=object->metaObject();
intcount=metaobject->propertyCount();
for(inti=0;i<count;++i){
QMetaProperty metaproperty=metaobject->property(i);
constchar*name=metaproperty.name();
QVariant value=object->property(name);
...
}
在以上代码,
ASimpleExample
假定我们有一个类MyClass,它继承了我们用
classMyClass:publicQObject
{
Q_OBJECT
Q_PROPERTY(PrioritypriorityREADpriorityWRITEsetPriorityNOTIFYpriorityChanged)
Q_ENUMS(Priority)
public:
MyClass(QObject *parent=0);
~MyClass();
enumPriority{High,Low,VeryHigh,VeryLow};
voidsetPriority(Prioritypriority)
{
m_priority=priority;
emitpriorityChanged(priority);
}
Prioritypriority()const
{returnm_priority;}
signals:
voidpriorityChanged(Priority);
private:
Prioritym_priority;
};
READ函数是const并且返回属性的类型,WRITE返回void并带有属性类型的一个参数。元对象编译器执行这些要求。
给定一个指向MyClass对象的指针或者一个指向MyClass实例的
MyClass*myinstance=newMyClass;
QObject *object=myinstance;
myinstance->setPriority(MyClass::VeryHigh);
object->setProperty("priority","VeryHigh");
在例子中,在MyClass中定义并用
一个类似的宏,
DynamicProperties
注意:dynamic属性被添加到每个实例的根,它们被添加到
和
PropertiesandCustomTypes
属性类型是自定义类型的需要用AddingAdditionalInformationtoaClass
Q_CLASSINFO("Version","3.0.0")
和其他元数据一样,类信息也可以通过运行时的元数据对象获取。
相关文章推荐
- Qt容器类(总结)
- Qt状态机框架
- Qt新建线程的方法(有QRunnable,QThreadPool,moveToThread和QtConcurrent的例子)
- QtSoap调用Web Service(QtSoap是非官方应用)
- QTableWidget 导出到csv表格
- 文本导出到pdf文件(使用QPrinter和QPainter和QTextDocument)
- PyQt5 笔记(05):信号/槽
- QTableWidget排序问题
- Qt实现不同Treewidget之间拖拽
- Qt实现QQ好友下拉列表(用QListView实现,所以还得定义它的Model)
- Qt同步线程(比较清楚,而且QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition 每个都有例子)
- QTabWidget 实现类似QQ聊天窗口(拖动分离出新的窗口)
- Qt 状态机框架学习(没学会)
- Qt 智能指针学习(7种QT智能指针和4种std智能指针)
- qt 使用xlslib操作execl
- 使用Qt库时出现winsock2.h和windos.h包含顺序错误
- PyQt5 笔记(04):主窗口卡死问题
- Ogre3D嵌入Qt框架 之 小结
- 分享一个自己写的QT小游戏-玛丽奥医生
- Qt 学习之路 2(31):贪吃蛇游戏(1)