文章源码来自《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、运行结果图: