QObject与线程QThread的关系

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,不会发生对该对象或其子对象的事件处理,因为它们不再与任何线程相关联。

警告:这个函数不是线程安全的;当前线程必须与当前线程关联性相同。换句话说,这个函数只能将一个对象从当前线程“推”到另一个线程,它不能从任意线程“拉”一个对象到当前线程。然而,这个规则有一个例外:没有线程关联的对象可以被“拉”到当前线程
 

QML中的线程可以使用QThread实现。QThread是Qt框架中用于线程处理的类,它可以在后台执行耗时操作,避免阻塞主线程。在QML中,你可以通过将QThread与自定义的QObject子类结合使用来创建线程。 首先,你需要创建一个继承自QObject的子类,作为线程的工作对象。在这个子类中,你可以实现具体的耗时操作。然后,将该对象移动到QThread的上下文中,以便在新线程中执行。 下面是一个简单的示例: ```cpp// MyWorker.hclass MyWorker : public QObject{ Q_OBJECTpublic: explicit MyWorker(QObject *parent = nullptr); public slots: void doWork(); signals: void workFinished(); }; // MyWorker.cppMyWorker::MyWorker(QObject *parent) : QObject(parent) { } void MyWorker::doWork() { // 执行耗时操作 // ... // 发送信号表示工作完成 emit workFinished(); } ``` 然后,在QML中创建一个QThread对象,并将工作对象移动到该线程中: ```qmlimport QtQuick2.0Item { id: root // 创建线程对象 property var thread: Qt.createQmlObject('import QtQuick2.0; import QtQuick.Controls2.0; QtObject { id: thread; function start() { worker.doWork(); } }', root) // 创建工作对象 property var worker: Qt.createQmlObject('import QtQuick2.0; MyWorker {}', root) // 当工作完成时的处理 Connections { target: worker onWorkFinished: { // 工作完成的处理逻辑 } } Component.onCompleted: { // 移动工作对象到线程中 worker.moveToThread(thread); // 启动线程 thread.start(); } } ``` 在这个示例中,我们创建了一个名为`MyWorker`的QObject子类,并在其中实现了耗时操作。然后,在QML中创建了一个`QThread`对象和一个`MyWorker`对象,并将`MyWorker`对象移动到线程中。最后,使用`start()`方法启动线程并执行工作。 请注意,为了正确管理线程和对象的生命周期,你可能需要在适当的时候调用`thread.quit()`和`thread.wait()`来停止线程和等待线程结束。 希望这个例子能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u010787096

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值