99网
您的当前位置:首页Qt5学习之路教程24:Qt5多线程例子2

Qt5学习之路教程24:Qt5多线程例子2

来源:99网

文章源码来自《Qt5.9 C++开发指南》,有改动。

一、界面设计

1、建立工程

2、建立资源文件夹、并导入图片

3、设计界面并设置属性

界面设计完成

二、功能实现

1、建立头文件

并写入代码

#include    <QThread>

class QDiceThread : public QThread
{
    Q_OBJECT
private:
    int     m_seq=0;//掷骰子次数序号
    int     m_diceValue;//骰子点数
    bool    m_Paused=true; //掷一次骰子
    bool    m_stop=false; //停止线程
protected:
    void    run() Q_DECL_OVERRIDE;  //线程任务
public:
    QDiceThread();

    void    diceBegin();//掷一次骰子
    void    dicePause();//暂停
    void    stopThread(); //结束线程
signals:
    void    newValue(int seq,int diceValue); //产生新点数的信号
};

2、建立对应qdicethread.cpp文件,并写入代码

#include "qdicethread.h"
#include    <QTime>

QDiceThread::QDiceThread()
{

}

void QDiceThread::diceBegin()
{ //开始掷骰子
    m_Paused=false;
}

void QDiceThread::dicePause()
{//暂停掷骰子
    m_Paused=true;
}

void QDiceThread::stopThread()
{//停止线程
    m_stop=true;
}

void QDiceThread::run()
{//线程任务
    m_stop=false;//启动线程时令m_stop=false
    m_seq=0; //掷骰子次数
    qsrand(QTime::currentTime().msec());//随机数初始化,qsrand是线程安全的

    while(!m_stop)//循环主体
    {
        if (!m_Paused)
        {
            m_diceValue=qrand(); //获取随机数
            m_diceValue=(m_diceValue % 6)+1;
            m_seq++;
            emit newValue(m_seq,m_diceValue);  //发射信号
        }
        msleep(500); //线程休眠500ms
    }

//  在  m_stop==true时结束线程任务
    quit();//相当于  exit(0),退出线程的事件循环
}

3、在dialog.h中添加如下代码

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

#include    "qdicethread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

private:
    QDiceThread   threadA;

protected:
    void    closeEvent(QCloseEvent *event);


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

private slots:
    void    onthreadA_started();
    void    onthreadA_finished();
    void    onthreadA_newValue(int seq, int diceValue);

    /********文本清除**********/
    void    txtClear();

    /*********暂停**************/
    void    diceEnd();

    /*********开始*************/
    void    diceBegin();

    /*********结束线程***********/
    void    stopThread();

    /*********开始线程***********/
    void    startThread();

private:
    Ui::Dialog *ui;
};
#endif // DIALOG_H

4、对应函数如下:

void Dialog::closeEvent(QCloseEvent *event)
{ //窗口关闭事件,必须结束线程
    if (threadA.isRunning())
    {
        threadA.stopThread();
        threadA.wait();
    }
    event->accept();
}
void Dialog::onthreadA_started()
{//线程的started()信号的响应槽函数
    ui->LabA->setText("Thread状态:thread started");
}
void Dialog::onthreadA_finished()
{//线程的 finished()信号的响应槽函数
    ui->LabA->setText("Thread状态:thread finished");
}
void Dialog::onthreadA_newValue(int seq,int diceValue)
{//QDiceThread的newValue()信号的响应槽函数,显示骰子次数和点数
    QString  str=QString::asprintf("第 %d 次掷骰子,点数为:%d",seq,diceValue);
    ui->plainTextEdit->appendPlainText(str);

    QPixmap pic; //图片显示
    QString filename=QString::asprintf(":/dice/images/d%d.jpg",diceValue);
    pic.load(filename);
    ui->LabPic->setPixmap(pic);
}
void Dialog::txtClear()
{
    ui->plainTextEdit->clear();
}
void Dialog::diceEnd()
{
    //暂停 掷骰子按钮
    threadA.dicePause();
    ui->btnDiceBegin->setEnabled(true);
    ui->btnDiceEnd->setEnabled(false);

}
void Dialog::diceBegin()
{
    //开始 掷骰子按钮
    threadA.diceBegin();
    ui->btnDiceBegin->setEnabled(false);
    ui->btnDiceEnd->setEnabled(true);
}
void Dialog::startThread()
{
    //启动线程 按钮
    threadA.start();

    ui->btnStartThread->setEnabled(false);
    ui->btnStopThread->setEnabled(true);

    ui->btnDiceBegin->setEnabled(true);
    ui->btnDiceEnd->setEnabled(false);
}
void Dialog::stopThread()
{
    threadA.stopThread();//结束线程的run()函数执行
    threadA.wait();//

    ui->btnStartThread->setEnabled(true);
    ui->btnStopThread->setEnabled(false);

    ui->btnDiceBegin->setEnabled(false);
    ui->btnDiceEnd->setEnabled(false);
}

5、对应信号槽connect

    connect(&threadA,SIGNAL(started()),this,SLOT(onthreadA_started()));
    connect(&threadA,SIGNAL(finished()),this,SLOT(onthreadA_finished()));

    connect(&threadA,SIGNAL(newValue(int,int)),this,SLOT(onthreadA_newValue(int,int)));

    connect(ui->btnClear,      SIGNAL(clicked(bool)), this, SLOT(txtClear()));
    connect(ui->btnDiceBegin,  SIGNAL(clicked(bool)), this, SLOT(diceBegin()));
    connect(ui->btnDiceEnd,    SIGNAL(clicked(bool)), this, SLOT(diceEnd()));
    connect(ui->btnStartThread,SIGNAL(clicked(bool)), this, SLOT(startThread()));
    connect(ui->btnStopThread, SIGNAL(clicked(bool)), this, SLOT(stopThread()));

6、运行结果图:

 

因篇幅问题不能全部显示,请点此查看更多更全内容