17、Qt线程(二):QObject::moveToThread

一、功能说明

1、创建子类,通过QObject::moveToThread函数把子类放入子线程中;

2、程序启动,初始化子线程

3、点击“开始”按钮启动定时器,子线程每隔1秒向主线程发送累加数;

4、点击"停止"按钮,停止定时器;

二、项目创建

1、新建Qt Widgets Application应用,名称为MoveToThread,基类选择QMainWindow;

2、MainWindow.ui中放入两个Push Button按钮,第一个text改为“开始”,objectNme改为startPushButton,第二个text改为“停止”,objectNme改为stopPushButton;

3、添加新的C++类,名称为MyObject,基类设置为QObject

4、注:

①通过moveToThread函数把子类放入子线程中,子类中的函数都在子线程中运行;

②子类和主类通过信号和槽的方式通信,相当于子线程和主线程通信;

三、代码演示

1、myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QTimer>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = nullptr);
    ~MyObject();

signals:
    void sendTimerData(int); //给主线程发送累加数

public slots:
    void systemInit(); //初始化

    void doStartSendData(); //定时器开始

    void doStopSendData(); //定时器停止

private slots:
    void doTimer(); //定时器槽函数

private:
    QTimer *m_timer; //定时器对象
    int sendValue; //累加数
};

#endif // MYOBJECT_H

2、myobject.cpp

#include "myobject.h"
#include <QDebug>
#include <QThread>

MyObject::MyObject(QObject *parent) : QObject(parent)
{
    qDebug() << "创建子线程id:" << QThread::currentThreadId();
}

MyObject::~MyObject()
{
    if(m_timer->isActive())
    {
        m_timer->stop();
    }
}

/**
* @brief MyObject::systemInit 初始化
*/
void MyObject::systemInit()
{
    sendValue = 0;
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &MyObject::doTimer);

    qDebug() << "初始化 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyObject::doStartSendData 定时器开始
*/
void MyObject::doStartSendData()
{
    qDebug() << "定时器开始id:" << QThread::currentThreadId();
    if(!m_timer->isActive())
    {
        m_timer->start(1000);
    }
}

/**
* @brief MyObject::doStopSendData 定时器停止
*/
void MyObject::doStopSendData()
{
    qDebug() << "定时器停止id:" << QThread::currentThreadId();
    if(m_timer->isActive())
    {
        m_timer->stop();
    }
}

/**
* @brief MyObject::doTimer 定时器槽函数
*/
void MyObject::doTimer()
{
    sendValue++;
    qDebug() << sendValue << "发送数据 子线程id:" << QThread::currentThreadId();
    emit sendTimerData(sendValue); //给主线程发送累加数
}

3、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include "myobject.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void doTimerData(int); //接收累加数

signals:
    void startSendData(); //开始定时器

    void stopSendData(); //停止定时器

private slots:
    void on_startPushButton_clicked();

    void on_stopPushButton_clicked();

private:
    Ui::MainWindow *ui;

    QThread *m_myThread; //线程对象
    MyObject *m_myObject; //自定义类对象
};

#endif // MAINWINDOW_H

4、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "主线程id:" << QThread::currentThreadId();

    m_myThread = new QThread;
    m_myObject = new MyObject;
    //类放入子线程
    m_myObject->moveToThread(m_myThread);
    //当子线程开始时,调用systemInit函数进行初始化
    connect(m_myThread, &QThread::started, m_myObject, &MyObject::systemInit);
    //当子线程结束时,调用deleteLater函数删除子类对象
    connect(m_myThread, &QThread::finished, m_myObject, &QObject::deleteLater);
    connect(m_myThread, &QThread::finished, m_myThread, &QObject::deleteLater);
    //控制子类开始定时器
    connect(this, &MainWindow::startSendData, m_myObject, &MyObject::doStartSendData);
    //控制子类停止定时器
    connect(this, &MainWindow::stopSendData, m_myObject, &MyObject::doStopSendData);
    //接收子线程数据
    connect(m_myObject, &MyObject::sendTimerData, this, &MainWindow::doTimerData);
    m_myThread->start(); //运行线程
}

MainWindow::~MainWindow()
{
    if(m_myThread)
    {
        m_myThread->quit();
        m_myThread->wait();
    }

    delete ui;
}

/**
* @brief MainWindow::doTimerData 接收子线程发送的累加数
* @param value
*/
void MainWindow::doTimerData(int value)
{
    qDebug() << value << "MainWindow id:" << QThread::currentThreadId();
}

/**
* @brief MainWindow::on_startPushButton_clicked 子线程开始
*/
void MainWindow::on_startPushButton_clicked()
{
    emit startSendData();
}

/**
* @brief MainWindow::on_stopPushButton_clicked 子线程停止
*/
void MainWindow::on_stopPushButton_clicked()
{
    emit stopSendData();
}

四、运行测试

先点击开始,一会再点击停止,输出框输出如下内容,根据线程id来区分不同的线程

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值