53黑马QT笔记之Qt下创建新线程之Qt5版本

1 创建新线程步骤:

1)自定义一个类,必须继承于QOject,但函数名可以是任意,不一定为run。
2)创建自定义类对象myT(一般作为主线程的成员)。 不能指定父对象this,因为后面要将该对象移动到QThraead对象。
3)创建QThread类对象thread(一般作为主线程的成员)。
4)将自定义类对象移动到子线程中,自定义类就相当于一个子线程。 myT.movetoThread(thread);
5)启动子线程。 thread.start(); 但与Qt4版本与区别,这里只是启动了线程,线程函数还没启动。
6)启动线程函数,但只能通过信号和槽启动。所以一般是通过按钮启动。
7)以上步骤已经完整创建一个新线程了,但是一般在新线程处理完复杂数据都会发射一个信号,该信号带一个或多个参数,返回给主进程使用。这一点下一篇的线程画图会使用到。

2 Qt5版本解决上两篇程序卡顿问题:

1)自定义类头文件:

#ifndef MYTHREAD_QT5_H
#define MYTHREAD_QT5_H

#include <QObject>

class MyThread_qt5 : public QObject          //qt4继承的类为QThread
{
    Q_OBJECT
public:
    explicit MyThread_qt5(QObject *parent = 0);

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

    void setFlag(bool flag);                 //由于isStop为私有,所以定义公有函数调用

signals:
    isDone();                                //线程处理函数完毕信号

private:
    bool isStop;                             //标志位,用于跳出循环,进而可以在外面改变标志位结束线程

public slots:
};

#endif // MYTHREAD_QT5_H

2)自定义类.cpp文件:

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

MyThread_qt5::MyThread_qt5(QObject *parent) : QObject(parent)
{
    isStop=false;                 //构造时默认为false
}

void MyThread_qt5::dealMsg()
{
        while(false == isStop)
        {
            QThread::sleep(1);
            emit isDone();        //每隔一秒发送信号
            qDebug()<<"子线程号: "<<QThread::currentThread();
        }

}

void MyThread_qt5::setFlag(bool fg)
{
    isStop=fg;                    //默认为false,若有外部传参fg则改变
}

3)主线程头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QThread>
#include"mythread_qt5.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void timeOUt();          //处理每一秒发射的信号槽函数

    void dealClose();        //防止不按stop而直接按右上角colse,而导致的线程没有关闭的槽函数

signals:
    startThread();           //触发线程处理函数的信号

private slots:
    void on_buttonstart_clicked();

    void on_buttonstop_clicked();

private:
    Ui::Widget   *ui;
    MyThread_qt5 *myT;      //自定义线程对象
    QThread      *thread;   //线程对象
};

#endif // WIDGET_H

4)主线程.cpp文件:

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>

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

    myT= new MyThread_qt5;  //不能指定父对象,故他要手动delete.线程不能处理图形界面即对话框这种框,但可以利用他利用他带参数的信号传出来到主线程 connect的第五个参数

    thread= new QThread(this);

    myT->moveToThread(thread);



    qDebug()<<"主线程号: "<<QThread::currentThread();

    // 调用线程处理函数
    connect(this,&Widget::startThread,myT,&MyThread_qt5::dealMsg); //参数1不熟,可由参数2得出
    // 线程数据处理完毕
    connect(myT,&MyThread_qt5::isDone,this,&Widget::timeOUt);
    // 防止不按stop而直接按右上角colse,而导致的线程没有关闭
    connect(this,&Widget::destroyed,this,dealClose);

}

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

// 关键槽函数 启动新线程去处理多任务
void Widget::on_buttonstart_clicked()
{
    if(thread->isRunning() == true)
    {
        return;                      //线程还在继续没必要start
    }

    myT->setFlag(false);

    thread->start();                 //只是启动线程,没有启动线程函数
    //直接调自定义线程函数,导致主线程与子线程id一样,即处于同一线程
    //myT->dealMsg();
    //只能通过信号和槽的方式调用   即再定义一个信号去触发自定义类的dealMsg(),然后通过发送该信号就可以调用了
    emit startThread();              // 必须通过信号和槽调用线程函数与间接调用run不一样

}


//处理每一秒发射的信号槽函数
void Widget::timeOUt()
{
    static int i=0;
    i++;
    ui->lcdNumber->display(i);
}

void Widget::on_buttonstop_clicked()
{
    if(thread->isRunning() == false)
    {
        return;                            //如果停止就没必要再继续. 按钮一般都有作这些判断.  嫌多可以不写
    }


    myT->setFlag(true);                    // 设置了标志位,但重新开始按下start时也要将其设回false,以至于可以继续循环
    thread->quit();
    thread->wait();                        // while的标志位设置先看下一条的注释,在进行解决
                                           // 仍然不能完整关闭线程 可以用标志位去解决 即将while(1)中的1改成相应标志位   即上面要先改变标志位
}

void Widget::dealClose()
{
    on_buttonstop_clicked();               // 直接调用就行
    delete myT;                            // 因为他没有指定父对象
}

5)主函数:一样的。

6)ui界面:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值