//首先,如果大家大家需要用到OPENGL,可以使用QT,网上有个GLWidget的教程做得很不错
今天先是把QT多线程的代码粘上来,然后把读取立体模型的源码发一下(适用于FEKO的.mesh模型)
//让QT把控制台显示出来,请在pro文件中加入CONFIG += console
//transactionthread.h
#ifndef TRANSACTIONTHREAD_H
#define TRANSACTIONTHREAD_H
#include <QImage>
#include <QMutex>
#include <QQueue>
#include <QThread>
#include <QWaitCondition>
class Transaction//用户可以对图片进行相关操作的抽象基类
{
public:
virtual ~Transaction() { }//需要通过一个Transaction指针来删除Transaction子类实例
virtual QImage apply(const QImage &image) = 0;
virtual QString message() = 0;
};
class FlipTransaction : public Transaction
{
public:
FlipTransaction(Qt::Orientation orientation);
QImage apply(const QImage &image);
QString message();
private:
Qt::Orientation orientation;
};
class ResizeTransaction : public Transaction
{
public:
ResizeTransaction(const QSize &size);
QImage apply(const QImage &image);
QString message();
private:
QSize size;
};
class ConvertDepthTransaction : public Transaction
{
public:
ConvertDepthTransaction(int depth);
QImage apply(const QImage &image);
QString message();
private:
int depth;
};
class TransactionThread : public QThread
{
Q_OBJECT
public:
TransactionThread();
~TransactionThread();
void addTransaction(Transaction *transact);
void setImage(const QImage &image);
QImage image();
signals:
void transactionStarted(const QString &message);
void allTransactionsDone();
protected:
void run();//run()函数在线程内执行,其他函数(包括构造函数和析构函数均是在主线程中被调用)
private:
QImage currentImage;//保存事务应用的图片
QQueue<Transaction *> transactions;//待处理的事务队列
QWaitCondition transactionAdded;//一个等待条件,当有新的事务添加到队列的时候,用于触发线程
QMutex mutex;//防止currentImage和transactions成员变量并发访问
};
#endif
//transactionthread.cpp
#include <QtGui>
#include "transactionthread.h"
Transaction * const EndTransaction = 0;
FlipTransaction::FlipTransaction(Qt::Orientation orientation)
{
this->orientation = orientation;
}
QImage FlipTransaction::apply(const QImage &image)
{
return image.mirrored(orientation == Qt::Horizontal,
orientation == Qt::Vertical);
}
QString FlipTransaction::message()
{
if (orientation == Qt::Horizontal) {
return QObject::tr("Flipping image horizontally...");
} else {
return QObject::tr("Flipping image vertically...");
}
}
ResizeTransaction::ResizeTransaction(const QSize &size)
{
this->size = size;
}
QString ResizeTransaction::message()
{
return QObject::tr("Resizing image...");
}
QImage ResizeTransaction::apply(const QImage &image)
{
return image.scaled(size, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
}
ConvertDepthTransaction::ConvertDepthTransaction(int depth)
{
this->depth = depth;
}
QImage ConvertDepthTransaction::apply(const QImage &image)
{
QImage::Format format;
switch (depth) {
case 1:
format = QImage::Format_Mono;
break;
case 8:
format = QImage::Format_Indexed8;
break;
case 24:
default:
format = QImage::Format_RGB32;
}
return image.convertToFormat(format);
}
QString ConvertDepthTransaction::message()
{
return QObject::tr("Converting image depth...");
}
TransactionThread::TransactionThread()
{
start();
}
TransactionThread::~TransactionThread()
{
//清空事务队列,并给队列添加一个专门用的EndTransaction标记,然后在基类析构函数被隐式调用之前,触发线程并使用
//QThread::wait函数等待它结束为止
{
QMutexLocker locker(&mutex);
while (!transactions.isEmpty())
delete transactions.dequeue();
transactions.enqueue(EndTransaction);
transactionAdded.wakeOne();
}
//调用wait之前,QMutexlocker的析构函数会在其内部程序模块的末尾解锁互斥量,调用wait函数之前解锁互斥量非常重要
//否则程序以死锁的情况结束,次线程永远等待互斥量被解锁,而主线程则在进一步执行之前保持互斥量并等待次线程执行结束
wait();
}
void TransactionThread::addTransaction(Transaction *transact)
{
//所有对transaction成员变量的访问都由一个互斥量保护起来,因为主线程或许会在次线程遍历所有事务的同时通过addTransaction
//修改这些成员变量(重要)
QMutexLocker locker(&mutex);
transactions.enqueue(transact);
//把事务添加到事务队列,如果事务线程没有运行,就触发它
transactionAdded.wakeOne();
}
void TransactionThr