本次以掷色子作为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,让他强制退出
运行效果如图:

启动线程以后:

线程运行一段时间:

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

被折叠的 条评论
为什么被折叠?



