QObject 介绍
QObject 是 Qt对象模型的核心。该模型的核心特征是具有一种非常强大的无缝对象通信机制,即信号和槽。您可以使用connect ()将信号连接到槽,并使用disconnect ()断开连接。为避免永无止境的通知循环,您可以使用blockSignals ()临时阻止信号。
QObjects 在对象树中组织自己。当你创建一个以另一个对象为父对象的 QObject 时,该对象会自动将自己添加到父对象的children () 列表中。父级获得对象的所有权;即,它会在自己的析构函数中自动删除它的所有孩子。您也可以选择使用findChild () 或findChildren ()按名称查找自己的孩子对象。
每个对象都有一个objectName (),它的类名可以通过相应的metaObject ()方法找到。
当一个对象被删除时,它会发出一个destroy () 信号。您可以捕获此信号以避免对 QObject进行悬空引用。
QObjects可以通过event ()接收事件,并选择性的过滤其他对象的事件。
同样重要的是,QObject 在 Qt 中提供了基本的计时器支持;请参阅QTimer以获得对计时器的高级支持。
还有所有 Qt widgets都继承 QObject。
QObject 既没有复制构造函数也没有赋值运算符。
线程亲和力
一个 QObject 实例被称为具有线程亲和性,是说它live在某个线程中。当 QObject 接收到排队的信号或发布的事件时,插槽或事件处理程序将在对象所live的线程中运行。
注意:如果 QObject 没有线程亲和性(即如果thread () 返回零),或者如果它存在于没有运行事件循环的线程中,则它无法接收排队信号或发布的事件。
默认情况下,QObject 存在于创建它的线程中。可以使用thread ()查询对象live的线程,并使用moveToThread ()更改对象live的线程。
所有 QObject 必须与其父对象存在于同一线程中。所以有如下约定:
- 如果涉及的两个 QObject 存在于不同的线程中,setParent () 将失败。
- 当一个 QObject 被移动到另一个线程时,它的所有子对象也将被自动移动。
- 如果 QObject 有父对象,则moveToThread () 将失败。
- If QObjects are created within QThread::run(), they cannot become children of the QThread object because the QThread does not live in the thread that calls QThread::run().
相关函数:
void QObject::moveToThread(QThread *targetThread)
更改此对象及其子对象的线程亲和性。如果对象有父对象,则不能移动它。事件处理将在targetThread 中继续。
要将对象移动到主线程,使用QApplication::instance () 获取指向当前应用程序的指针,然后使用QApplication::thread () 获取应用程序所在的线程。
如果targetThread是nullptr
,则此对象及其子对象的所有事件处理都将停止,因为它们不再与任何线程关联。
请注意,该对象的所有活动计时器都将被重置。计时器首先在当前线程中停止,然后在targetThread 中重新启动(以相同的间隔)。因此,在线程之间不断移动对象可以无限期地推迟计时器事件。
一个QEvent::ThreadChange事件在线程亲和性改变之前被发送到这个对象。您可以处理此事件以执行任何特殊处理。请注意,发布到此对象的任何新事件都将在targetThread 中处理,前提是它不是nullptr
: 当它是时nullptr
,不会发生对该对象或其子对象的事件处理,因为它们不再与任何线程相关联。
警告:这个函数不是线程安全的;当前线程必须与当前线程关联性相同。换句话说,这个函数只能将一个对象从当前线程“推”到另一个线程,它不能从任意线程“拉”一个对象到当前线程。然而,这个规则有一个例外:没有线程关联的对象可以被“拉”到当前线程。