QT特性-QObject、MOC、MOS
2015-04-30 11:30
169 查看
QT特性-QObject、MOC、MOS
sf2gis@163.com
2015年1月7日
原理:
QObject提供MOS的功能接口。
Q_OBJECT标识启用元对象系统。
MOC生成元对象系统的标准C++代码。
方法:
QObject::metaObject():返回相关的QMetaObject对象。
QMetaObject::className():返回当前类名(字符串)。
QObject::inherits():判断是否继承自指定类。
QObject::tr()/trUtf8():转码。
QObject::Property()/setProperty():动态属性。
QMetaObject::newInstance():创建新实例对象。
qobject_cast<type *>(obj):高级类型转换,不需要编译器支持RTTI,支持dll。
由于无Q_OBJECT宏时,无法使用QObject的特性,建议无论何时都使用Q_OBJECT。
QMetaObject::connectSlotsByName(this):自动连接机制,将this中槽函数与子对象建立连接。
QObject在释放时会发出destroyed信号。
QObject会对所在线程的所有对象发布信号。
所有权是指父对象释放时,会先将子对象释放。
QObject具有一个objectName属性,可以通过setObjectName()设置。
QObject所属的类可以通过QMetaObject::className()获取。
如果对象树中相关对象被释放,则自动将相关指针设置为0。
示例:
qDebug()<<pListener->objectName ()<<pListener->metaObject()->className ();
需要使用copy的地方,只能使用指针代替。
如果使用了,会出现以下错误:
error: C2248: 'QObject::QObject' : cannot access privatemember declared in class 'QObject'
参考:http://qimo601.iteye.com/blog/1523936
原理:由MOS提供。
方法:
Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
属性可以通过MOS读写。
属性可以通过MOS动态的从QObject添加、删除。
声明属性后,在QtCreator中,右击-》重构-》Generate missing Porperties会自动生成声明所有的函数和成员变量(成员变量变自动添加m_前缀)。
示例:
class QTask : public QObject
{
Q_OBJECT
Q_PROPERTY(int iTest READ getTest WRITEsetTest)
private:
int m_iTest;
public:
intgetTest() const
{
returnm_iTest;
}
public slots:
voidsetTest(int arg)
{
m_iTest = arg;
}
}
方法:setProperty(属性名,值)。
如果值有效,动态属性不存在,则添加动态属性。
如果值有效,属性存在,则改写。
如果值无效(QVariant()默认是无效值),则删除此动态属性,如果此属性不是动态的(显示声明的不是动态的),则无影响。
可以动态的添加属性或删除属性,动态属性只添加到QObject对象中,不影响MetaObject。并且也只能通过动态方法读写。
示例:
QTask *pT= new QTask;
pT->setTest (5);
qDebug()<<pT->getTest ();
int iTest= pT->property ("iTest").toInt ();
pT->setProperty ("abc",77);
int iDyn =pT->property ("abc").toInt ();
pT->setProperty("abc",QVariant());
int iDyn2= pT->property ("abc").toInt ();
原理:接收OS事件,处理相应事件。
1) 事件与信号的区别:事件只向事件系统发送,由事件系统唯一分发;而信号则向所有QObject广播,由QObject决定处理。
2) 事件对应Windows中的消息,从OS中获取,然后发送到指定对象。事件循环在一个线程中唯一存在,同步(send)/异步(post)操作事件列表。信号也是同步(directconnect)或异步(queuedconnection)处理连接,如果异步,则等待时间片空闲时,发送异步信号队列。
方法:
1) 处理事件
事件(QEvent类的对象)是各种事件发生时,发送的通知信息。一般响应时需要重写基类的相应的响应函数。
QObject::event()是最顶级的事件处理函数,需要自己判断事件的类型。
格式:on_ObjectName_Signal(params)。
操作函数:QMetaObject::connectSlotsByName(this)。
详见:qt-信号槽signalslot机制.docx
因此,在使用QObject时,需要注意,如果有进入消息循环的slot函数,或者在消息循环中使用的对象,则要使用deleteLater()。
参考:
http://stackoverflow.com/questions/4888189/how-delete-and-deletelater-works-wrt-to-signals-and-slots-in-qt
参考:
http://stackoverflow.com/questions/6095946/how-can-i-get-the-qobjectdeletelater-to-zero-the-object
示例:
信号
connect(m_pFw,SIGNAL(destroyed()),this,SLOT(nullWatcher()));
槽
void QMapFrameTask::nullWatcher()
{
m_pFw = NULL;
}
MOC在Qt的bin目录下moc.exe。
使用方法
moc .h文件–o .moc文件
这里.moc文件就是标准的c++头文件。
在使用时,需要将所有使用信号和槽的头文件转化为.moc文件,然后将moc文件包含在头文件中(不要包含在cpp文件中)。
sf2gis@163.com
2015年1月7日
1 Meta-Object System元对象系统
目标:Qt的元对象系统提供了QObject的基本功能,包含信号-槽,动态属性,运行时类型信息(RTTI)等。原理:
QObject提供MOS的功能接口。
Q_OBJECT标识启用元对象系统。
MOC生成元对象系统的标准C++代码。
方法:
QObject::metaObject():返回相关的QMetaObject对象。
QMetaObject::className():返回当前类名(字符串)。
QObject::inherits():判断是否继承自指定类。
QObject::tr()/trUtf8():转码。
QObject::Property()/setProperty():动态属性。
QMetaObject::newInstance():创建新实例对象。
qobject_cast<type *>(obj):高级类型转换,不需要编译器支持RTTI,支持dll。
由于无Q_OBJECT宏时,无法使用QObject的特性,建议无论何时都使用Q_OBJECT。
QMetaObject::connectSlotsByName(this):自动连接机制,将this中槽函数与子对象建立连接。
2 QObject
QObject是所有Qt类的基类。QObject在释放时会发出destroyed信号。
QObject会对所在线程的所有对象发布信号。
2.1 objecttree/parent-children/ownership
QObject存在对象树,父对象拥有子对象的所有权。所有权是指父对象释放时,会先将子对象释放。
QObject具有一个objectName属性,可以通过setObjectName()设置。
QObject所属的类可以通过QMetaObject::className()获取。
如果对象树中相关对象被释放,则自动将相关指针设置为0。
示例:
qDebug()<<pListener->objectName ()<<pListener->metaObject()->className ();
2.2 私有的Copy构造函数
所有QObject的子类,无法使用copy构造函数(将copy构造函数设置为私有,无法继承),因为信号槽模式,要求所有的QObject对象是唯一的。需要使用copy的地方,只能使用指针代替。
如果使用了,会出现以下错误:
error: C2248: 'QObject::QObject' : cannot access privatemember declared in class 'QObject'
参考:http://qimo601.iteye.com/blog/1523936
2.3 属性系统PropertySystem
目标:提供统一,跨编译器和平台的标准属性系统。原理:由MOS提供。
方法:
Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
属性可以通过MOS读写。
属性可以通过MOS动态的从QObject添加、删除。
声明属性后,在QtCreator中,右击-》重构-》Generate missing Porperties会自动生成声明所有的函数和成员变量(成员变量变自动添加m_前缀)。
示例:
class QTask : public QObject
{
Q_OBJECT
Q_PROPERTY(int iTest READ getTest WRITEsetTest)
private:
int m_iTest;
public:
intgetTest() const
{
returnm_iTest;
}
public slots:
voidsetTest(int arg)
{
m_iTest = arg;
}
}
2.3.1动态属性添加、删除
目标:在对象中动态添加、删除属性。方法:setProperty(属性名,值)。
如果值有效,动态属性不存在,则添加动态属性。
如果值有效,属性存在,则改写。
如果值无效(QVariant()默认是无效值),则删除此动态属性,如果此属性不是动态的(显示声明的不是动态的),则无影响。
可以动态的添加属性或删除属性,动态属性只添加到QObject对象中,不影响MetaObject。并且也只能通过动态方法读写。
示例:
QTask *pT= new QTask;
pT->setTest (5);
qDebug()<<pT->getTest ();
int iTest= pT->property ("iTest").toInt ();
pT->setProperty ("abc",77);
int iDyn =pT->property ("abc").toInt ();
pT->setProperty("abc",QVariant());
int iDyn2= pT->property ("abc").toInt ();
2.4 事件系统EventSystem
目标:实现OS中事件的处理。原理:接收OS事件,处理相应事件。
1) 事件与信号的区别:事件只向事件系统发送,由事件系统唯一分发;而信号则向所有QObject广播,由QObject决定处理。
2) 事件对应Windows中的消息,从OS中获取,然后发送到指定对象。事件循环在一个线程中唯一存在,同步(send)/异步(post)操作事件列表。信号也是同步(directconnect)或异步(queuedconnection)处理连接,如果异步,则等待时间片空闲时,发送异步信号队列。
方法:
1) 处理事件
事件(QEvent类的对象)是各种事件发生时,发送的通知信息。一般响应时需要重写基类的相应的响应函数。
QObject::event()是最顶级的事件处理函数,需要自己判断事件的类型。
2.5 自动连接机制
使用指定的命令方式,moc可以分解将自动建立连接。只能建立在QObject及其子对象之间。格式:on_ObjectName_Signal(params)。
操作函数:QMetaObject::connectSlotsByName(this)。
详见:qt-信号槽signalslot机制.docx
2.6 QObject与deleteLater()
由于QObject提供了信号-槽机制,在消息循环中需要保持所有对象可用。为了避免在消息循环中引用被释放的指针,Qt对内存的管理引入了deleteLater()来代替delete(),用于保证需要释放的对象在消息循环结束后能够自动释放。因此,在使用QObject时,需要注意,如果有进入消息循环的slot函数,或者在消息循环中使用的对象,则要使用deleteLater()。
参考:
http://stackoverflow.com/questions/4888189/how-delete-and-deletelater-works-wrt-to-signals-and-slots-in-qt
2.6.1释放QObject
一般在释放时,会将指针置NULL(防止野指针),在使用deteteLater()后,不能直接赋值NULL,应该使用destroyed()信号的响应槽函数置NULL。参考:
http://stackoverflow.com/questions/6095946/how-can-i-get-the-qobjectdeletelater-to-zero-the-object
示例:
信号
connect(m_pFw,SIGNAL(destroyed()),this,SLOT(nullWatcher()));
槽
void QMapFrameTask::nullWatcher()
{
m_pFw = NULL;
}
3 MOC元对像编译工具
将qt的信号和槽转化为标准的C++代码。MOC在Qt的bin目录下moc.exe。
使用方法
moc .h文件–o .moc文件
这里.moc文件就是标准的c++头文件。
在使用时,需要将所有使用信号和槽的头文件转化为.moc文件,然后将moc文件包含在头文件中(不要包含在cpp文件中)。
4 信号-槽
参见:qt-信号槽signalslot机制.docx相关文章推荐
- QT多重继承的时候,要把QObject放在最前面,否则报错——C++认为人性本恶,默认都是私有的,这点和Delphi的世界观不一样
- Qt源码分析之QObject
- Qt文档翻译之-QObject
- Qt源码分析之QObject
- 深入理解QT的SIGNAL\SLOT机制(三):QObject::connect函数
- [Qt]QObject::connect: Cannot queue arguments of type 'QString&'
- Qt5.0 的新特性
- Qt自定义的类关于继承自QObject的出现的问题
- QT 编译警告 qobject_cast to QGraphicsItem will not work
- Qt: 内建对话框(各种对话框都有了,且用到了qobject_cast解析sender的技术)
- QObject是QT所有类的基类,QObject是Qt Object Model的核心
- Qt 5.9 新特性
- 必须要了解的QT特性!
- Qt源码分析之QObject
- Qt 静态函数QMetaObject::connectSlotsByName(QObject * object)按命名规则自动connect,不需要手动connect
- Qt日记(3)-360新版特性界面实现(3)
- Qt对C++添加的新特性
- Qt 之 QObject
- QT4 thread和QObject关系详解
- 解读QT信号与槽机制里 QMetaObject::connectSlotsByName(QObject *o)的源码