QThread的初步使用

本次以掷色子作为qt多线程的例子,帮助理解qt多线程,自己学了几天像什么互斥锁信号量的线程同步网上的课程找了好多,越学越觉得他博大精深嘿嘿~还是自己来做一做嘿嘿~

多线程这里我们就不过多赘述,本程序较为简单,创建一个线程threadA来在后台掷色子,通过信号把掷色子的次数以及色子的点数传给主线程

首先我们要创建一个新的c++类文件:

变量就不解释了,旁边都有注释

tdicethread.h

#ifndef TDICETHREAD_H
#define TDICETHREAD_H

#include <QThread>

class TDicethread : public QThread
{
    Q_OBJECT
public:
    TDicethread(QObject *parent = nullptr);//把构造函数放到对象树中管理
    void dicebegin();//开始
    void dicepause();//暂停
    void dicestop();//整个线程的暂停
private:
    int m_seq=0;//丢了第几次
    int m_dicevalue;//丢的值是多少
    bool m_pause;//是不是暂停状态
    bool m_stop;//整个线程是不是暂停状态


    // QThread interface

protected:
    virtual void run() override;
signals:
    void newvalue(int seq,int m_dicevalue);
};



#endif // TDICETHREAD_H

我在头文件里面重写了run函数,实现写在cpp文件里面,当他满足m_pause和m_stop的条件时候获取[1,7)的数字作为色子点数,然后休息一秒,太快看左边和右边看不过来,把参数放入信号里面传给主线程。

tdicethread.cpp

#include "tdicethread.h"
#include<QRandomGenerator>

TDicethread::TDicethread(QObject *parent):QThread(parent) {}

void TDicethread::dicebegin()//开始
{
    m_pause=false;
}

void TDicethread::dicepause()//暂停
{
    m_pause=true;
}

void TDicethread::dicestop()//整个线程的暂停
{
    m_stop=true;
}

void TDicethread::run()//重构run函数
{
    m_stop=false;
    m_pause=true;
    m_seq=0;
    while(!m_stop){
        if(!m_pause){
        ++m_seq;
        m_dicevalue=QRandomGenerator::global()->bounded(1,7);//[1,6)
        emit newvalue(m_seq,m_dicevalue);
        }
        sleep(1);
    }
}

该类用qthread构造基类并把它挂到对象树上进行管理

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    TDicethread *threadA;

private slots:
    void do_started();
    void do_finished();
    void do_newvalue(int seq,int dicevalue);
    void on_actThread_Run_triggered();
    void on_actDice_Run_triggered();
    void on_actDice_Pause_triggered();
    void on_actThread_Quit_triggered();
    void on_actClose_triggered();
    void on_actClear_triggered();

    // QWidget interface
protected:
    virtual void closeEvent(QCloseEvent *event) override;
};



#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
class TDicethread;
class QThread;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    threadA=new TDicethread(this);
    connect(threadA,&TDicethread::started,this,&MainWindow::do_started);
    connect(threadA,&TDicethread::finished,this,&MainWindow::do_finished);
    connect(threadA,&TDicethread::newvalue,this,&MainWindow::do_newvalue);

}

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

void MainWindow::do_started()
{
    ui->statusbar->showMessage("Thread状态:Thread started");
    ui->actDice_Run->setEnabled(true);
    ui->actDice_Pause->setEnabled(true);
    ui->actThread_Quit->setEnabled(true);
    ui->actThread_Run->setEnabled(false);
}

void MainWindow::do_finished()
{
    ui->statusbar->showMessage("Thread状态:Thread finished");
    ui->actDice_Run->setEnabled(false);
    ui->actDice_Pause->setEnabled(false);
    ui->actThread_Quit->setEnabled(false);
    ui->actThread_Run->setEnabled(true);
}

void MainWindow::do_newvalue(int seq, int dicevalue)
{
    QString str=QString::asprintf("第%d次掷色子,投掷的点数为:%d",seq,dicevalue);
    ui->plainTextEdit->appendPlainText(str);

    QString filename=QString::asprintf(":/dice/images/d%d.jpg",dicevalue);
    QPixmap pic(filename);
    ui->labPic->setPixmap(filename);
}


void MainWindow::on_actThread_Run_triggered()
{
    threadA->start();
}


void MainWindow::on_actDice_Run_triggered()
{
    threadA->dicebegin();
    ui->actDice_Run->setEnabled(false);
    ui->actDice_Pause->setEnabled(true);
}


void MainWindow::on_actDice_Pause_triggered()
{
    threadA->dicepause();
    ui->actDice_Run->setEnabled(true);
    ui->actDice_Pause->setEnabled(false);
}


void MainWindow::on_actThread_Quit_triggered()
{
    threadA->dicestop();
}


void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(threadA->isRunning()){
       threadA->terminate();//强制退出线程
       threadA->wait();//等他运行完
    }
    event->accept();
}





void MainWindow::on_actClose_triggered()//可以空着,不能没有
{

}

主程序把threadA发送的信号接受并用里面的参数完成显示相关的功能,再一个是实现action功能,另外就是支线程是在后台运行的,如果直接关闭整个窗口他并没有停下来,要为他重写一下窗口closeevent,让他强制退出

运行效果如图:

启动线程以后:

线程运行一段时间:

左边点数和右边是对应的,完成,这时候点结束线程或者直接关闭都可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值