初学Qt线程,此实例只是对Qt单一线程的使用,另外结合信号槽实现ui界面与子线程之间数据的传输,可以解决线程在运行的过程中,关闭对话框程序崩溃的问题。
此实例要实现的效果图如下:
界面控件的类,对象表如下:
界面启动后,起初停止线程按钮是置灰的,点击开始线程按钮,停止线程按钮不再置灰,在textBrowser中显示1 2 3 4…等数字,点击停止线程按钮会停止打印,注:点击停止线程后不会立即停止打印,而是有一定的延时,再次点击开始线程按钮,textBrowser中继续显示数字,只要显示的数字小于某一个数值,不点击停止线程按钮或者关闭对话框,线程就会一直运行,另外可以在点击开始线程按钮前后,可以点击GetTime按钮和Smile按钮。
可以分为线程类的编写,对话框类对线程的使用,代码如下:
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
#include <QMutex>
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QObject * parent = nullptr);
~MyThread();
protected:
void run();
public:
void DoSomething();
void DislaySomthing();
void StopThread();
signals:
void signGetTime(QString &strTime);
void signString(const QString &str);
void signSmileString(const QString &str);
private:
qint32 m_a;
bool m_Status;
QMutex m_mutex;
};
#endif // MYTHREAD_H
MyThread.h.cpp
#include "mythread.h"
#include <QDateTime>
MyThread::MyThread(QObject * parent):QThread (parent),m_a(0),m_Status(false)
{
}
MyThread::~MyThread()
{
}
void MyThread::run()
{
m_Status = false;
while(m_a < 30000)
{
sleep(1);
m_a++;
emit signString(tr("%1 ").arg(m_a));
QMutexLocker mutex(&m_mutex);
if(m_Status)
{
return ;
}
}
}
void MyThread::DoSomething()
{
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
emit signGetTime(current_date);
}
void MyThread::DislaySomthing()
{
emit signSmileString(tr("if you belive yourself,you can do it at most persent of 99."));
}
void MyThread::StopThread()
{
QMutexLocker mutex(&m_mutex);
m_Status = true;
}
Dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
class MyThread;
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void on_pushButtonGetTime_clicked();
void on_pushButtonSmile_clicked();
void on_pushButtonStart_clicked();
void on_pushButtonStop_clicked();
void slotGetTime(QString & str);
void slotDisplaySmile(const QString &str);
void slotString(const QString &Str);
private:
Ui::Dialog *ui;
MyThread *m_Thread;
};
#endif // DIALOG_H
Dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include "mythread.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
m_Thread = new MyThread(this);
connect(m_Thread,&MyThread::signGetTime,this,&Dialog::slotGetTime);
connect(m_Thread,&MyThread::signSmileString,this,&Dialog::slotDisplaySmile);
connect(m_Thread,&MyThread::signString,this,&Dialog::slotString);
}
Dialog::~Dialog()
{
if(m_Thread->isRunning())
{
m_Thread->StopThread();
m_Thread->wait();
}
delete ui;
}
void Dialog::on_pushButtonGetTime_clicked()
{
m_Thread->DoSomething();
}
void Dialog::on_pushButtonSmile_clicked()
{
m_Thread->DislaySomthing();
}
void Dialog::on_pushButtonStart_clicked()
{
if(m_Thread->isRunning())
{
return ;
}
m_Thread->start();
ui->pushButtonStop->setEnabled(true);
}
void Dialog::on_pushButtonStop_clicked()
{
m_Thread->StopThread();
ui->pushButtonStop->setEnabled(false);
}
void Dialog::slotGetTime(QString &str)
{
ui->lineEditTime->setText(str);
}
void Dialog::slotDisplaySmile(const QString &str)
{
ui->textEditSmile->setText(str);
}
void Dialog::slotString(const QString &Str)
{
QString strSrc = ui->textBrowser->toPlainText();
strSrc += Str;
ui->textBrowser->setText(strSrc);
}
main.cpp
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
以上是一个简单的线程,总结下来,继承QThread的线程类,必须在该类中重写run()函数,在run()函数中编写线程要做的事,线程启动时通过线程类对象或指针调用start()函数,线程关闭时可以使用bool变量来控制线程的关闭,也可通过quit(),wait()来等待线程的关闭,不建议使用terminate()来终止正在运行的线程,因为这样线程的终止取决于系统的调用策略,即随机调用性。