详细描述
QObject类是所有Qt对象的基类。
QObject是Qt Object Model的核心。这个模型的核心特征是,为了无缝对象通信的,叫做signals和slots的一个强大的机制。你可以使用connect()连接一个信号和槽,使用disconnect()销毁该连接。为了避免永远不会结束的通知循环,你可以使用blockSignals()临时地组织信号。保护函数connectNotify()和disconnectNotify()让追踪连接成为可能。
QObjects使用object trees组织自己。当你创建一个使用其他对象作为父类的QObject时,对象会自动将自己添加到父类的children()列表中。父类独占对象:例如,它会在自己的析构函数中自动删除它的孩子。你可以通过名字和可选的类型,使用findChildren()查找一个孩子对象。
每个对象有一个objectName()和自己的类名,类名可以通过对应的metaObject()找到(参考QMetaObject::className())。你可以通过使用inherits()函数确定,在QObject继承体系中,对象是否继承自另一个对象。
当一个对象被删除,它发出一个destroyed()信号。你可以捕捉这个信号来避免对QObjects的悬空引用。
QObjects可以通过event()接收事件,过滤其它对象的事件。细节参考installEventFilter()和eventFilter()。一个方便的句柄,childEvent(),为了捕捉子类的信号可以重新实现。
最后但同样重要的,Qt中QObject提供了基本的定时器;为了定时器更高级别的支持参考QTimer。
注意,Q_OBJECT宏是任何的对象实现信号、槽或属性的基础。你也需要在源文件中运行Meta Object Compiler。我们强烈建议在所有的QObject的子类中使用该宏,无论它们是否真的使用信号,槽或属性,如果不这样做,可能会引起确定的函数产生陌生的行为。
所有继承自QObject的Qt widgets。方便的函数isWidgetType()返回该对象是否确实为一个widget。它比qobject_cast<QWidget *>(obj)或obj->inherits("QWidget")快很多。
一些QObject函数,例如,children(),返回一个QObjectList,QObjectList是QList<QObject *>的类型。
线程亲和性
一个Object实例,是说有一个线程亲和性,或者说它在一个明确的线程中存活。当一个QObject接收到一个queuedsignal或一个posted event,槽函数或事件句柄会在对象存活的线程中运行。
注意:如果一个QObject没有线程亲和性(也就是,如果thread()返回零),或者它存活在一个没有正在运行事件循环的线程中,它将不能接收排队的信号或传递来的事件。
默认情况,一个QObject存活在被创建的线程中。一个对象的线程亲和性可以使用thread()查询,使用moveToThread()修改。
所有QObjects必须与它们的父类存活在同一个线程中。下列:
- 如果两个QObjects对象在不同的线程中,setParent()会失败。
- 当一个QObject移动到另外的线程,它的子类也会自动移动。
- 如果QObject有一个父类,moveToThread()会失败。
- 如果QObject对象通过QThread::run()创建,它们不能成为QThread的子类,因为QThread不在叫做QThread::run()的线程中。
注意:一个QObject的成员变量不会自动成为它的子类。父类-子类关系必须通过传递一个指针给子类的constructor,或者调用setParent()。没有这一步,当moveToThread()被调用时,对象的成员变量会保留在旧的线程中。
没有拷贝构造或赋值操作
QObject没有任何的拷贝构造或赋值操作。这是设计。实际上,它们被声明,但是使用宏Q_DISABLE_COPY()放在了私有部分。实际上,所有继承自QObject(直接或间接)的Qt类使用该宏,将它们的拷贝构造和赋值操作声明为私有的。原因可以在Qt的Object Model页的Identity vs Value的讨论中找到。
主要的结论是,你应该在,临时将QObject子类作为值的地方,使用指针指向QObject(或者你的QObject子类)。例如,没有拷贝构造,你不能使用QObject子类作为值,存放到容器类中。你必须存放指针。
自动连接
Qt的meta-object系统提供了一个机制,自动连接QObject子类和它们的子类之间的信号和槽。只要对象使用合适的对象名称定义,槽函数遵循一个简单的命名转换,连接可以在运行期间通过QMetaObject::connectSlotsByName()函数执行。
uic生成代码:授权该函数开启自动连接那些使用Qt Designer创建的在form上的widgets。更多关于使用Qt Designer的自动连接,在Qt Designer手册中的Using a Designer UI File in Your Application中给出。
动态属性
从Qt 4.2,动态属性可以在运行期间被添加和从QObject实例中移除。动态属性不需要在编译期声明,因为,作为静态属性它们提供了同样的优势,使用API操作-使用property()来读属性,使用setProperty()来写属性。
国际化 (I18n)
所有的QObject子类支持Qt的转换特征,将一个用户接口应用转为不同的语言成为可能。为了支持用户可见文本转换,它必须使用tr()函数包装。这在文档Writing Source Code for Translation中详细解释。