Qt笔记——多线程

这个例子是,点击开始按钮,数字累加,点击停止按钮,数字不动。

 

1,新建一个类,里面是子线程的内容

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>

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

    //线程处理函数
    void myTimeout();
    void setFlag(bool flag = false);
signals:
    void mySignal();

public slots:

private:
    bool isStop;
};

#endif // MYTHREAD_H

 

#include "mythread.h"
#include <QThread>
#include <QDebug>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
    isStop = false;
}

void MyThread::myTimeout()
{
    while(isStop == false)
    {
        QThread::sleep(1);
        emit mySignal();
        qDebug()<<"子线程号: "<<QThread::currentThread();
        if(isStop == true)
        {
            break;
        }
    }
}

void MyThread::setFlag(bool flag)
{
    isStop = flag;
}

 

2,主线程中创建QTread 对象,然后将子线程类通过moveToThread()中来

并且不直接调用子程序(子线程),通过主程序发出一个信号,然后子程序接受到信号,开始运行

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include "mythread.h"
#include <QDebug>
namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
    void dealSignal();
    void dealClose();

signals:
    void startThread();//启动子线程

private slots:
    void on_startBtn_clicked();

    void on_stopBtn_clicked();

private:
    Ui::MyWidget *ui;
    MyThread *myT;
    QThread *thread;
};

#endif // MYWIDGET_H
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>

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

    //动态分配空间,不能指定父对象
    myT = new MyThread;
    //创建子线程
    thread = new QThread(this);

    //把自定义线程加入到子线程中
    myT->moveToThread(thread);
    connect(myT,&MyThread::mySignal,this,&MyWidget::dealSignal);
    qDebug()<<"主线程号: "<<QThread::currentThread();
    connect(this,&MyWidget::startThread,myT,&MyThread::myTimeout);
    connect(this,&MyWidget::destroyed,this,&MyWidget::dealClose);

    //线程处理函数内部,不允许操作图形界面

    //connect()第五个参数的作用,连接方式:默认,队列,直接
    //多线程才有意义
    //默认的时候,如果是多线程,默认使用队列,如果是单线程,默认是用直接方式
    //队列:槽函数所在线程和接受者一样
    //直接:槽函数所在线程和发送者一样

}

void MyWidget::dealClose()
{
    on_stopBtn_clicked();
    delete myT;
}

void MyWidget::dealSignal()
{
    static int i = 0;
    i++;
    ui->lcdNumber->display(i);
}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::on_startBtn_clicked()
{
    if(thread->isRunning() == true)
    {
        return;
    }
    //启动线程,但是没有启动线程
    thread->start();
    myT->setFlag(false);
    //不能直接调用线程处理函数,直接调用导致线程处理函数和主线程在同一个线程
    //myT->myTimeout(); //错的
    //只能通过 signal-slot方式调用
    emit startThread();
}

void MyWidget::on_stopBtn_clicked()
{
    if(thread->isRunning() == false)
    {
        return;
    }
    myT->setFlag(true);
    thread->quit();
    thread->wait();
}

 

posted @ 2018-04-15 21:11  大蓝鲸  阅读(480)  评论(0编辑  收藏  举报