QT 主线程和任务线程通过信号交互

因为 qt线程中如果执行ui操作是很容易死机的,而且是不知道那的错误,所以分开执行,通过信号交互,但有时ui线程的单个任务比较久,所以需要等些时间,下面直接上代码,以做备份

主要是从树中取出一堆文件路径,把需要处理的路径加到线程后开始线程中处理,每处理一个后,要等单个任务处理完再进行下一个,可随时中止任务

调用主类:

#ifndef _PROJECT_MainUiClass_H_
#define _PROJECT_MainUiClass_H_

#include <QDockWidget>
#include "ui_MainUiClass.h"
#include "Processthread.h"
#include <QTreeWidgetItem>
#include <string>

class QVBoxLayout;
c

class MainUiClass : public QFrame
{
	Q_OBJECT

public:
	MainUiClass(QWidget *parent = 0);
	~MainUiClass();
	
    bool GetExportResComplate();
  	void SetExportResComplate(bool bFlag);
	void setProcess(int nExportprocess);
public slots:
	void ItemExportChanged(const QString ItmePath, const QString destPath, bool bFlag);

	void updateProcessLater();
  private:
	 
	   QProgressDialog *m_ProcessDlg;
	   bool m_bExportComplateFlag;
	   int mExportProgress;
	   Processthread *m_pProcessThread;
};

#endif
#include "stdafx.h"
#include "MainUiClass.h"

#include <QTreeWidgetItem>
#include "MyTreeCtrlClass.h"

#include <QMenu>
#include "dummy.h"


MainUiClass::MainUiClass(QWidget *parent)
: QFrame(parent)
{
	ui.setupUi(this);

	
	m_ProcessDlg = NULL;

	m_ProcessDlg = new QProgressDialog(this);
	m_ProcessDlg->setWindowModality(Qt::WindowModal);
	m_ProcessDlg->setWindowTitle(QString::fromLocal8Bit("资源导出中"));
	m_ProcessDlg->setCancelButton(NULL);
	m_ProcessDlg->setLabelText(QString::fromLocal8Bit("前期关联资源解析中,请稍候..."));
	m_ProcessDlg->show();
	m_ProcessDlg->setFixedHeight(60);
	m_ProcessDlg->setFixedWidth(200);
	//QPalette pal = palette();
	//pal.setColor(QPalette::Background, QColor(0x00, 0xff, 0x00, 0x00));
	//m_ProcessDlg->setPalette(pal);
	int currentScreen = QApplication::desktop()->screenNumber(m_ProcessDlg);//程序所在的屏幕编号
	QRect rect = QApplication::desktop()->screenGeometry(currentScreen);//程序所在屏幕尺寸
	m_ProcessDlg->move((rect.width() - m_ProcessDlg->width()) / 2, (rect.height() - m_ProcessDlg->height()) / 2);//移动到所在屏幕中间
	QTimer::singleShot(1000, this, SLOT(updateProcessLater()));
	m_ProcessDlg->hide();
	m_bExportComplateFlag = true;
	mExportProgress = -1;
	m_pProcessThread = NULL;
}

MainUiClass::~MainUiClass()
{
	if (m_pProcessThread)
	{
		m_pProcessThread->setStop(true);
		m_pProcessThread->exit(0);
	}
}



void MainUiClass::ExportResAll()
{
	
	if (m_bExportComplateFlag == false)
	{
		OutputWin::addError("正在执行线程,请不要重复操作!");
		return;
	}
	if (!m_pProcessThread)
	{
		m_pProcessThread = new Processthread();
		
	}

	m_pProcessThread->ClearAll();
	m_pProcessThread->setStop(true);

	QString strDestPath = "";
	QExportResDlg dlg(Q_NULLPTR,true);
	int code = dlg.exec();
	if (code == QDialog::Accepted)
	{
		strDestPath = dlg.m_strFilePath;
	}
	else
	{
		return;
	}

	int nCount = ui.treeWidget->topLevelItem(0)->childCount();
	if (nCount > 0)
	{
		QTreeWidgetItem* childItem = NULL;
		childItem = ui.treeWidget->topLevelItem(0)->child(0);
		if (childItem->text(0) == "XXXXXSet")
		{
		}
		else  if (nCount > 1)
		{
			childItem = ui.treeWidget->topLevelItem(1)->child(0);
			if (childItem->text(0) == "XXXXXset")
			{
			}
			else
			{
				OutputWin::addError("未查找到XXXXXset结点!");
				return;
			}
				
		}
		else
		{
			OutputWin::addError("未查找到XXXXXset结点!");
			return;
		}

		for (int i = 0; i < childItem->childCount(); i++)
		{
			MyTreeCtrlClass* itemFirst = dynamic_cast<MyTreeCtrlClass*>(childItem->child(i));
			if (itemFirst)
			{
				QString itemPath = itemFirst->getPath();
				//ExportRes(itemPath, strDestPath, false);
				m_pProcessThread->AddItemDir(itemPath);
			}
		}
		m_pProcessThread->SetDestItemDir(strDestPath);
		m_pProcessThread->setStop(false);
		m_bExportComplateFlag = false;
		mExportProgress = 0;
		QTimer::singleShot(1000, this, SLOT(updateProcessLater()));
		Object obj;
		Dummy dummy;
		obj.moveToThread(m_pProcessThread);
		QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot()));
		//防止重复连接信号
		QObject::disconnect(m_pProcessThread, SIGNAL(slot_onItemExportChanged(const QString, const QString, bool)), this, SLOT(ProcessItem(const QString, const QString, bool)));
		QObject::connect(m_pProcessThread, SIGNAL(ProcessItem(const QString, const QString, bool)), this, SLOT(ItemExportChanged(const QString, const QString, bool)));

		
		m_pProcessThread->start();
		dummy.emitsig();

	}

	
}


void MainUiClass::ItemExportChanged(const QString ItmePath, const QString destPath, bool bFlag)
{
	//进程中写入正在执行
	//if (m_pProcessThread)
	//{
	//	m_pProcessThread->setIsRunItem(true);
	//}
	ProcessItem(ItmePath, destPath, false);//处理单项任务,这里未实现
	//进程中写入正在结束
	if (m_pProcessThread)
	{
		m_pProcessThread->setIsRunItem(false);
	}
}


void MainUiClass::SetExportResComplate(bool bFlag)
{
	m_bExportComplateFlag = bFlag;
}


bool MainUiClass::GetExportResComplate()
{
	return m_bExportComplateFlag;
}
void MainUiClass::setProcess(int nExportprocess)
{
	mExportProgress = nExportprocess;
}


void MainUiClass::updateProcessLater()
{//进度条控制
	
	if (m_bExportComplateFlag == false)
	{
		if (mExportProgress>0)
		{
			m_ProcessDlg->setLabelText(QString::fromLocal8Bit("正在资源导出..."));
		}
		m_ProcessDlg->setValue(mExportProgress);
		qApp->processEvents();
		QTimer::singleShot(100, this, SLOT(updateProcessLater()));
	}
	else
	{
		m_ProcessDlg->setValue(100);
		m_ProcessDlg->hide();
		qApp->processEvents();
	}
}

线程类:

#ifndef Processthread_H
#define Processthread_H

#include <QThread>
#include <QMutex>  
class Processthread : public QThread
{
	Q_OBJECT

public:
	Processthread();
	~Processthread();

	
 
	void setStop(int bFlag); //m_threadRunFlag 0是默认状态,1是是否执行单项任务,2设置是否停止任务
	void ClearAll();
	void AddItemDir(QString strItem);//添加任务
signals:
	void ProcessItem(const QString ItmePath);//发送信号去处理任务
private:

	void run();
	QStringList m_listDir;
	int m_threadRunFlag;
	QString m_strDestDir;
	QMutex m_mutex;  //信号锁
};

#endif // Processthread_H
#include "Processthread.h"



Processthread::Processthread()
{
   // folderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
	//	QIcon::Normal, QIcon::Off);
//	folderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
//		QIcon::Normal, QIcon::On);

	m_stopFlag = 0;

}

Processthread::~Processthread()
{

}



void Processthread::setStop(bool bFlag)
{
	m_mutex.lock();
	m_stopFlag = bFlag;
	m_mutex.unlock();
}

void Processthread::run()
{
	MainUiClass *pProject = XXXXX::getSingle()->getMainUiClass();//得到全局指针
	if (pProject)
	{
		
		int nCount = m_listDir.size();//所有任务处理一次
		for (int i = 0; i < nCount; i++)
		{
			QString strItmePath = m_listDir.at(i);
			int nCurrentprocess = i*100.0f / nCount;
			pProject->setProcess(nCurrentprocess); //设置进度条
			m_mutex.lock();
			m_bRunItemFlag = true;
			m_mutex.unlock();

			emit slot_onItemExportChanged(strItmePath, m_strDestDir, false);
			//pProject->ExportRes(strItmePath, m_strDestDir, false);
			//等待输出信号
			
			m_mutex.lock();
			m_stopFlag  = 1;//表示开始执行单项任务
			m_mutex.unlock();
				
			while (1)
			{
				bool bFlagItemRunFlag = true;
				m_mutex.lock();
				bFlagItemRunFlag  = m_stopFlag;
				m_mutex.unlock();
				if (m_stopFlag == 0)
					break;
				if (m_stopFlag == 2)
						break;
				Sleep(100);
			}
			if (m_stopFlag == true)
				break;
		}
	}
    
	pProject->setProcess(100);//进度条设置。理论上发信号更号,我也不想改了, 相上面一样emit  slot_onItemExportChanged
	pProject->SetExportResComplate(true);  //全部完成了反馈给主任务
}


void Processthread::ClearAll()
{
	m_listDir.clear();
}

void Processthread::setIsRunItem(bool bFlag)
{
	m_mutex.lock();
	m_stopFlag = bFlag;
	m_mutex.unlock();
}

void Processthread::AddItemDir(QString strItem)
{
	m_listDir.push_back(strItem);
}

这个只是为了线程不卡,详细做什么没查,反正用习惯了就这么用的:

#ifndef DUMMY_H
#define DUMMY_H


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

class Dummy:public QObject 
{ 
    Q_OBJECT 
public: 
    Dummy(QObject* parent=0):QObject(parent)     {} 
public slots: 
    void emitsig() 
    { 
        emit sig(); 
    } 
signals: 
    void sig(); 
}; 
 
class Object:public QObject 
{ 
    Q_OBJECT 
public: 
    Object(){} 
public slots: 
    void slot() 
    { 
        qDebug()<<"from thread slot:" <<QThread::currentThreadId(); 
    } 
}; 

#endif // DUMMY_H
#include "dummy.h"


通过信号量函数修改,增加一个表示进度条的变量:我觉得不需要在线程中直接处理进度条了

void MainUiClass::ItemExportChanged(const QString ItmePath, const QString destPath, bool bFlag, int nExportprocess)
{
    if (nExportprocess >=100)
    {//表示任务处理完成了
        return;
    }
    mExportProgress = nExportprocess;



//其它执行单个任务

//再设置标志

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值