因为 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;
//其它执行单个任务
//再设置标志
}