一、QObject简介
class QObject
inmodule QtCore 模块
brief The QObject class is the base class of all Qt objects. QObject是所有Qt对象的基类。
QObject是Qt的核心{QObject Model}.该模型的核心特征是一个非常强大的无缝对象通信机制,其被称为{信号和槽}。您可以使用connect()将信号连接到插槽,并使用disconnect()破坏连接。为了避免永无止境的通知循环,你可以使用blockSignals()临时阻塞信号。受保护的函数connectNotify()和disconnectNotify()使跟踪连接成为可能。
QObjects在{对象树和所有权}{对象树}中组织自己。当您使用另一个对象作为父对象创建QObject时,该对象将自动将自己添加到父对象的children()列表中。父类获得对象的所有权;也就是说,它会在析构函数中自动删除它的子类。 可以使用findChild()或findChildren函数,通过名称和可选的类型查找对象。
每个对象都有一个objectName(),它的类名可以通过相应的metaObject()找到(参见QMetaObject::className())。您可以使用inherits()函数确定对象的类是否继承QObject继承层次结构中的另一个类。
当一个对象被删除时,它会发出一个destroyed()信号。您可以捕获此信号以避免对QObjects的悬空引用。
QObjects可以通过event()接收事件,并过滤其他对象的事件。详情请参见installEventFilter()和eventFilter()。可以重新实现一个方便的处理程序childdevent()来捕获子事件。
最后但并非最不重要的是,QObject在Qt中提供了基本的定时器支持;有关定时器的高级支持,请参阅QTimer。
注意,Q_OBJECT宏对于任何实现信号、槽或属性的对象都是强制性的。您还需要在源文件上运行{moc}{Meta Object Compiler}。 我们强烈建议在QObject的所有子类中使用这个宏,不管它们是否实际使用信号、槽和属性,因为不这样做可能会导致某些函数表现出奇怪的行为。
All Qt widgets inherit QObject. The convenience function
isWidgetType() returns whether an object is actually a widget. It
is much faster than
\l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
\e{obj}->\l{inherits()}{inherits}("QWidget").
所有Qt widgets都继承QObject。函数isWidgetType()返回对象是否实际上是一个widget。它比……快得多 {qobject_cast()}{qobject_cast}<QWidget *>({obj}) or {obj}->{inherits()}{inherits}("QWidget").
一些QObject函数,例如children(),返回一个QObjectList。QObjectList是QList<QObject *>的类型定义。
二、 Thread Affinity 线程亲和性、线程关联性
一个QObject实例有一个{线程关联性},或者它存在于一个特定的线程中。当QObject接收到{Qt::QueuedConnection}{排队信号}或{事件系统#发送事件}{发布事件}时,槽或事件处理程序将在该对象所在的线程中运行。
如果QObject没有线程关联性(即,如果thread()返回零),或者如果它生活在一个没有运行事件循环的线程中,那么它就不能接收队列信号或发布事件。
默认情况下,QObject存在于创建它的线程中。对象的线程关联可以使用thread()查询,并使用moveToThread()更改。
所有的qobject必须和它们的父线程在同一个线程中。
- 如果涉及的两个QObjects位于不同的线程中,setParent()将失败。
- 当一个QObject被移动到另一个线程时,它的所有子线程也将被自动移动。
- 如果QObject有父对象,moveToThread()将失败。
- 如果 QObjects 是在QThread::run()中创建的,它们就不能成为QThread对象的子对象,因为QThread不在调用QThread::run()的线程中。
QObject的成员变量不会自动成为它的子变量。父-子关系必须通过传递一个指向子对象{Q0bject()}{构造函数}的指针或调用setParent()来设置。如果没有这一步,当moveToThread()被调用时,对象的成员变量将保留在旧线程中。
target No copy constructor
三、No Copy Constructor or Assignment Operator 没有拷贝构造函数和赋值操作函数
QObject既没有复制构造函数,也没有赋值操作符。这是设计好的。实际上,它们是在{private}部分中使用宏Q_DISABLE_COPY()声明的。事实上,所有从QObject派生的Qt类(直接或间接)都使用这个宏来声明它们的复制构造函数和赋值操作符是私有的。推理可以在Qt {对象模型}页面上关于{Identity vs Value} {Identity vs Value}的讨论中找到。
其主要结果是,您应该使用指向QObject(或指向QObject子类)的指针,否则您可能会试图使用QObject子类作为值。例如,如果没有复制构造函数,就不能使用QObject的子类作为要存储在一个容器类中的值。必须存储指针。
四、Auto-Connection 自动连接
Qt的元对象系统提供了一种机制来自动连接QObject子类和它们的子类之间的信号和槽。只要使用合适的对象名称定义对象,并且插槽遵循简单的命名约定,就可以在运行时通过QMetaObject::connectSlotsByName()函数执行此连接。
uic生成调用此函数以启用的代码在使用{Qt Designer}创建的窗体上的widgets之间执行自动连接。关于使用自动连接与{Qt Designer}的更多信息,请参阅{Qt Designer}手册的{Using a Designer UI File in Your Application}部分。
五、Dynamic Properties 动态属性
从Qt 4.2开始,可以在运行时向对象实例添加和删除动态属性。 动态属性不需要在编译时声明,但它们提供了与静态属性相同的优点,并且可以使用相同的API进行操作——使用property()读取它们,使用setProperty()写入它们。
从Qt 4.3开始,Qt设计器的Widget编辑模式#属性编辑器}{Qt设计器}支持动态属性,标准Qt widgets 和用户创建的表单都可以被赋予动态属性。
六、Internationalization (I18n) 国际化
所有的QObject子类支持Qt的翻译特性,尽可能的将一个应用程序的用户接口翻译为不同的语言。
为了使用户可见的文本可翻译,必须将其包装在对tr()函数的调用中。这在{为翻译编写源代码}文档中有详细解释。
QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
{Object Trees & Ownership} 对象树 & 所属