初学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_OBJECTpublic: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()来终止正在运行的线程,因为这样线程的终止取决于系统的调用策略,即随机调用性。