《QT5.9 c++ 开发指南》第13章 QThread功能简介

先看一下QThread 类功能简单介绍

         将应用程序的线程称为主线程,额外创建的线程称为工作线程 。 一般在主线程里创建工作线程,井调用 start()开始执行工作线程的任务 。 start()会在 内 部调用 run()函数,进入工作线程的事件循环,在 run()函数里调用 exit()或 quit()可以结束线程的事件循环,或在主线程里调用 terminate() 强制结束线程。
         公共函数部分:


 那我们开始写一个小工程吧。

 

   

先看下运行的图吧:

页面布局如下:

这获取图片资源:

链接:图片资源      提取码:74g3 

提取后记得要加载在项目中。

好的,我们先需要写一个类 QDiceThread 继承与 QThread 如下面:

#ifndef QDICETHREAD_H
#define QDICETHREAD_H

#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;   //线程任务,重载run函数
public:
    QDiceThread();
    void diceBegin();  //掷一次骰子
    void dicePause(); //暂停
    void stopThread();  //结束线程
signals:
    void newValue(int seg,int diceValue); //产生新点数的信号  由主线程的槽函数响应
};

#endif // QDICETHREAD_H

对应的cpp:

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

QDiceThread::QDiceThread()
{

}
void QDiceThread::run()
{
    //线程任务
    m_stop = false; //启动线程 m_stop=false
    m_seq = 0; //掷骰子次数
    qsrand(uint(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),退出线程的事件循环
}



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

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

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

如果你编译过程中出现下面错误,可能是你在创建这个类的时候,没有选择继承 Q_OBJECT:

 

解决方案:

解决方案与错误分析

如果没有我们继续:

这个是dialog.h 文件:

#ifndef DIALOG_H
#define DIALOG_H

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

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT
private:
    QDiceThread  threadA;
protected:
    void closeEvent(QCloseEvent *event);

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();
private slots:
    //自定义槽函数
    void    onthreadA_started();
    void    onthreadA_finished();
    void    onthreadA_newValue(int seq, int diceValue);

    void on_btnStartThread_clicked();

    void on_btnDiceBegin_clicked();

    void on_btnDiceEnd_clicked();

    void on_btnStopThread_clicked();

    void on_btnClear_clicked();

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

这个是dialog.cpp 文件:

#include "dialog.h"
#include "ui_dialog.h"

void Dialog::closeEvent(QCloseEvent *event)
{
    //关闭窗口 并退出程序
    if(threadA.isRunning())
    {
        threadA.stopThread();
        threadA.wait();
    }
    event->accept();
}

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    //构造函数
    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)));

}

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

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::on_btnStartThread_clicked()
{
   //开始线程
    threadA.start(); //开始线程,会执行重载的run 函数
    ui->btnStartThread->setEnabled(false);
    ui->btnStopThread->setEnabled(true);

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

void Dialog::on_btnDiceBegin_clicked()
{
    //开始 掷骰子按钮
    threadA.diceBegin();
    ui->btnDiceBegin->setEnabled(false);
    ui->btnDiceEnd->setEnabled(true);
}

void Dialog::on_btnDiceEnd_clicked()
{
    //暂停 掷骰子按钮
    threadA.dicePause();
    ui->btnDiceBegin->setEnabled(true);
    ui->btnDiceEnd->setEnabled(false);
}

void Dialog::on_btnStopThread_clicked()
{
    //结束线程
    threadA.stopThread();
    threadA.wait();

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

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



void Dialog::on_btnClear_clicked()
{
    //清空文本 按钮
    ui->plainTextEdit->clear();
}

大部分功能都有中文解释了,请慢慢理解,可以看这本书,对比来。

希望大家多多学习进步。

发布了28 篇原创文章 · 获赞 7 · 访问量 4454

猜你喜欢

转载自blog.csdn.net/weixin_42126427/article/details/104472733