Qt 第二种线程

流程:

工程目录:

mythread.h:

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>

class MyThread : public QObject
{
    Q_OBJECT   //要使用信号和槽必须有的宏,
public:
    explicit MyThread(QObject *parent = 0);

    //线程处理函数
    void myTimerout();

    //由于bool isStop是私有的,需要定义一个公有接口,这里使用的是默认参数
    void setFlag(bool flag = true);

signals:

    void mySignal();

public slots:

private:
    bool isStop;

};

#endif // MYTHREAD_H

mywidget.h:

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

#include "mythread.h"

#include <QThread>//添加在这里作为全局

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_buttonStart_clicked();

    void on_buttonStop_clicked();

private:
    Ui::MyWidget *ui;

    MyThread *myT;

    QThread *thread;


};

#endif // MYWIDGET_H

mythread.cpp:

#include "mythread.h"

#include <QThread>//待会用到sleep函数

#include <QDebug>

MyThread::MyThread(QObject *parent) : QObject(parent)
{
    isStop = false;

}

void MyThread::myTimerout()
{
//    while(1)
//    {
//        //每隔一秒发射一次mySignal(),
//        QThread::sleep(1);

//        emit mySignal();

//        qDebug()<<"子线程号: "<<QThread::currentThread();
//    }
    //换成如下代码
    while(isStop == false)
    {
        //每隔一秒发射一次mySignal(),
        QThread::sleep(1);

        emit mySignal();

        qDebug()<<"子线程号: "<<QThread::currentThread();
        if (true == isStop)
        {
            break;
        }
    }
}

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

mywidget.cpp:

#include "mywidget.h"
#include "ui_mywidget.h"

#include <QDebug>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    //动态分配空间, 不能指定父对象,由于没有指定父对象,所以我们需要手动将其delete掉
    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::myTimerout);//只能通过signal - slot 方式调用

    connect(this,&MyWidget::destroyed,this,&MyWidget::dealclose);

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

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

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

void MyWidget::dealclose()
{
    on_buttonStop_clicked();
    delete myT;

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

void MyWidget::on_buttonStart_clicked()
{

    if (thread->isRunning() == true)
    {
        return;
    }
    //启动线程,但是没有启动线程处理函数
    thread->start();

    myT->setFlag(false );

    //不能直接调用线程处理函数
    //直接调用(即myT->myTimerout();),导致线程处理函数和主线程是在同一个线程

    //只能通过signal - slot 方式调用
    emit startThread();


}


void MyWidget::on_buttonStop_clicked()
{
    //在这里由于使用的是while(1),其实线程是不能退出的,这是因为quit()要等线程走完再退出,但是while(1)是死循环,走不完。
    //所以我们应该在while函数下功夫,即设置一个标志位,
    if(thread->isRunning() == false)
    {
        return;
    }
    myT->setFlag(true);

    thread->quit();
    thread->wait();
}

ui:

猜你喜欢

转载自www.cnblogs.com/doker/p/11162523.html