QT多線程(二)

前言

目的是在主線程中,使用信號和槽來執行一個子線程中的處理函數。

 

  • 當點擊start按鈕時,子線程每秒鐘發射一個信號(mySignal) 並在控制檯打印線程地址,主線程接收此信號執行數字累加。
  • 當點擊stop按鈕時,停止子線程,並釋放內存。
  • 當點擊關閉窗口按鈕時,可能子線程還在運行,此時就要觸發stop按鈕的信號執行停止子線程。

 

步驟

  1. 創建自定義類Thread繼承QObject,並在槽函數中寫相應的處理代碼。
  2. 在主線程中創建一個Thread的對象myT,和QThread(子線程)的對象thread。
  3. 將myT加入到子線程中。
  4. 啓動子線程thread(此時並沒有執行myT中的處理函數myTimerout())。
  5. 通過主線程的信號startThread()喚醒子線程的函數myTimerout()。
  6. 子線程中myTimerout()發射信號mySignal(),主線程接收執行dealSignal()。

 

代碼:

自定義類Thread:

thread.h

#include<QObject>
#include<QDebug>
#include<QThread>

class Thread : public QObject
{

	Q_OBJECT
public:
	Thread() ;

	void set_flag(bool x) ;

signals:
	void mySignal() ;

public slots:
	void myTimerout();

private:
	bool flag;
};

thread.cpp

#include"thread.h"
#include "QThread"

Thread::Thread()
{
	flag = false ;
}

void Thread::set_flag(bool x)
{
	this->flag = x ;
}

void Thread::myTimerout()
{
	while(!flag)
	{
		for(long long i = 0; i < 500000000; i++) ;

		emit mySignal() ;

		qDebug() << QThread::currentThread() ;
	}
}

 

classwindow.h

#ifndef CLASSWINDOW_H
#define CLASSWINDOW_H

#include <QtGui/QMainWindow>
#include <QDebug>
#include <QThread>
#include "ui_classwindow.h"
#include "thread.h"

class ClassWindow : public QMainWindow
{
	Q_OBJECT

public:
	ClassWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
	~ClassWindow();

private:
	Ui::ClassWindowClass ui;
	Thread *myT;
	QThread *thread ;

signals:
	void startThread() ;

public slots:
	void startButton_licked() ;
	void stopButton_clicked() ;
	//處理子線程發射的信號的函數
	void dealSignal() ;
};

#endif // CLASSWINDOW_H

 

classwindow.cpp

#include "classwindow.h"

ClassWindow::ClassWindow(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);

	//創建自定義線程類,動態分配空間,不能指定父對象
	myT = new Thread ;

	//創建子線程
	thread = new QThread(this) ;

	//把自定義線程加入到子線程中
	myT->moveToThread(thread) ;

	qDebug() << QThread::currentThread() ;

	//主線程發射信號,子線程接收開始執行函數myTimout()
	QObject::connect(this, SIGNAL(startThread()), myT, SLOT(myTimerout())) ;

	//子線程中的myTimout()每秒發射一個信號,主線程執行dealSignal
	QObject::connect(myT, SIGNAL(mySignal()), this, SLOT(dealSignal()));

	//關閉按鈕觸發stop按鈕來停止子線程
	QObject::connect(this, SIGNAL(destroyed()), this, SLOT(stopButton_clicked())) ;

	//線程處理函數不能操作圖形用戶界面
}

ClassWindow::~ClassWindow()
{

}



void ClassWindow::startButton_licked()
{
	if(thread->isRunning())
		return ;

	myT->set_flag(false) ;
	thread->start() ;
	emit startThread() ;
}

void ClassWindow::stopButton_clicked()
{
	if(thread->isFinished())
		return ;

	myT->set_flag(true) ;
	thread->quit() ;
	thread->wait() ;

	delete myT ;
}

void ClassWindow::dealSignal()
{
	static int i = 0;
	i++;
	ui.lcdNumber->display(i) ;
}

 

運行時可以看到,控制檯上顯示的主線程和子線程不是一個地址。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章