我们都知道一个程序一般只有一个线程,但是单独的线程面对一些小号耗时的操作效果会不好,引入单独的线程解决耗时的操作,并且与主线程之间处理好同步与数据交互,用处十分大。
今天通过一个简单的掷色子程序描述这一过程:
程序运行如下:
这个就是创建一个带有ui设计器的项目,然后在项目中创建一个C++类QDiceThread
然后大家跟我复制代码:
qdicethread.h:
#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;
public:
QDiceThread();
void diceBegin();
void dicePause();
void stopThread();
signals:
void newValue(int seq,int diceValue);
};
#endif // QDICETHREAD_H
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_seq=0;
//随机数初始化 qsrand是线程安全的
qsrand(QTime::currentTime().msec());
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);
}
quit();
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qdicethread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QDiceThread threadA;
protected:
void closeEvent(QCloseEvent *event);
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_btn_qd_clicked();
void on_btn_start_clicked();
void on_btn_down_clicked();
void on_btn_over_clicked();
void on_btn_clear_clicked();
//自定义槽函数
void onthreadA_started();
void onthreadA_finished();
void onthread_newValue(int seq,int diceValue);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#pragma execution_character_set("utf-8")
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
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(onthread_newValue(int,int)));
}
void MainWindow::onthreadA_started()
{
ui->label_state->setText("线程状态:thread started");
}
void MainWindow::onthreadA_finished()
{
ui->label_state->setText("线程状态:thread over");
}
void MainWindow::onthread_newValue(int seq, int diceValue)
{
QString str=QString::asprintf("第 %d 次掷色子,点数为: %d",seq,diceValue);
ui->plainTextEdit->appendPlainText(str);
}
//启动线程
void MainWindow::on_btn_qd_clicked()
{
threadA.start();
//启动线程
ui->btn_qd->setEnabled(false);
//结束线程
ui->btn_over->setEnabled(true);
//开始按钮
ui->btn_start->setEnabled(true);
//暂停按钮
ui->btn_down->setEnabled(false);
}
//结束线程
void MainWindow::on_btn_over_clicked()
{
threadA.stopThread();
threadA.wait();
ui->btn_qd->setEnabled(true);
ui->btn_over->setEnabled(false);
ui->btn_start->setEnabled(false);
ui->btn_down->setEnabled(false);
}
//开始
void MainWindow::on_btn_start_clicked()
{
threadA.diceBegin();
ui->btn_start->setEnabled(false);
ui->btn_down->setEnabled(true);
}
//暂停
void MainWindow::on_btn_down_clicked()
{
threadA.dicePause();
ui->btn_start->setEnabled(true);
ui->btn_down->setEnabled(false);
}
//清空
void MainWindow::on_btn_clear_clicked()
{
ui->plainTextEdit->clear();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(threadA.isRunning()){
threadA.stopThread();
threadA.wait();
}
event->accept();
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>951</width>
<height>817</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>881</width>
<height>571</height>
</rect>
</property>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="geometry">
<rect>
<x>20</x>
<y>90</y>
<width>831</width>
<height>471</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="btn_qd">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>启动按钮</string>
</property>
</widget>
<widget class="QPushButton" name="btn_start">
<property name="geometry">
<rect>
<x>150</x>
<y>10</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>开始</string>
</property>
</widget>
<widget class="QPushButton" name="btn_down">
<property name="geometry">
<rect>
<x>290</x>
<y>10</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>暂停</string>
</property>
</widget>
<widget class="QPushButton" name="btn_over">
<property name="geometry">
<rect>
<x>430</x>
<y>10</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>结束线程</string>
</property>
</widget>
<widget class="QPushButton" name="btn_clear">
<property name="geometry">
<rect>
<x>570</x>
<y>10</y>
<width>111</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>清空文本</string>
</property>
</widget>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>161</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>线程</string>
</property>
</widget>
<widget class="QLabel" name="label_state">
<property name="geometry">
<rect>
<x>20</x>
<y>640</y>
<width>611</width>
<height>111</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>951</width>
<height>17</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
运行后程序如上所示,这个程序的点还是很多复习了Qthread的知识,Qtime等等,有用的很多,C++的面向对象体现的淋漓尽致。
大家不懂留言,我会一一解答