//main.cpp#include <QApplication>#include "mythread.h"#include <QTextCodec>int main(int argc, char *argv[]){ QTextCodec *codec = QTextCodec::codecForName("CP1251"); QTextCodec::setCodecForTr(codec); QApplication app(argc, argv); Program ProgramWin; ProgramWin.resize(400, 300); ProgramWin.show(); return app.exec();}
//mythread.h#ifndef Program_H#define Program_H#include <QMainWindow>#include "transactionthread.h"class QAction;class QLabel;class QMenu;class Program : public QMainWindow{ Q_OBJECTpublic: Program();protected: void closeEvent(QCloseEvent *event);private slots: void run(); void allTransactionsDone();private: void createActions(); void createMenus(); void addTransaction(Transaction *transact); TransactionThread thread; QLabel *imageLabel; QMenu *fileMenu; QAction *runAction;};#endif
//mythread.cpp#include <QtGui>#include "mythread.h"#include "ui_resizedialog.h"Program::Program(){ imageLabel = new QLabel; imageLabel->setBackgroundRole(QPalette::Dark); imageLabel->setAutoFillBackground(true); imageLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); setCentralWidget(imageLabel); createActions(); createMenus(); statusBar()->showMessage(tr("Ready"), 2000); connect(&thread, SIGNAL(transactionStarted(const QString &)), statusBar(), SLOT(showMessage(const QString &))); connect(&thread, SIGNAL(transactionRun(const QString &)), statusBar(), SLOT(showMessage(const QString &))); connect(&thread, SIGNAL(allTransactionsDone()), this, SLOT(allTransactionsDone()));}void Program::closeEvent(QCloseEvent *event){ event->accept();}void Program::run(){ addTransaction(new Run());}void Program::addTransaction(Transaction *transact){ thread.addTransaction(transact); runAction->setEnabled(false);}void Program::allTransactionsDone(){ runAction->setEnabled(true); setWindowModified(true); statusBar()->showMessage(tr("Ready"), 2000);}void Program::createActions(){ runAction = new QAction(tr("&Run.."), this); runAction->setStatusTip(tr("Запуск")); connect(runAction, SIGNAL(triggered()), this, SLOT(run()));}void Program::createMenus(){ fileMenu = menuBar()->addMenu(tr("&Run")); fileMenu->addAction(runAction);}
//transactionthread.h#ifndef TRANSACTIONTHREAD_H#define TRANSACTIONTHREAD_H#include <QMutex>#include <QQueue>#include <QThread>#include <QWaitCondition>#include <QString>class Transaction{public: virtual ~Transaction() { } virtual QString apply(const QString &str) = 0; virtual QString message() = 0;};class Run : public Transaction{public: Run(); QString apply(const QString &str) QString message();private: int i;};class TransactionThread : public QThread{ Q_OBJECTpublic: TransactionThread(); ~TransactionThread(); void addTransaction(Transaction *transact);signals: void transactionStarted(const QString &message); void transactionRun(const QString &message); void allTransactionsDone();protected: void run();private: QQueue<Transaction *> transactions; QWaitCondition transactionAdded; QMutex mutex;};#endif
//transactionthread.h#include <QtGui>#include "transactionthread.h"Transaction * const EndTransaction = 0;Run::Run(){}QString Run::apply(const QString &str){ QString str2; //непосредственно расчеты int i=1; int a = 10; while (a !=i){ a=a/i; i++; str2 = QString::number(i,10); }return (str2);}QString Run::message(){ return QObject::tr("Выполняю расчет...");}TransactionThread::TransactionThread(){ start();}TransactionThread::~TransactionThread(){ { QMutexLocker locker(&mutex); while (!transactions.isEmpty()) delete transactions.dequeue(); transactions.enqueue(EndTransaction); transactionAdded.wakeOne(); } wait();}void TransactionThread::addTransaction(Transaction *transact){ QMutexLocker locker(&mutex); transactions.enqueue(transact); transactionAdded.wakeOne();}void TransactionThread::run()//в этой функции будем выполнять долгие расчеты, при этом интерфейс приложения зависать не должен{ Transaction *transact = 0; forever { { QMutexLocker locker(&mutex); if (transactions.isEmpty()) transactionAdded.wait(&mutex); transact = transactions.dequeue(); if (transact == EndTransaction) break; } emit transactionStarted(transact->message()); //выводим надпись для статусбара QString str = transact->apply(str); //выполняем необходимые расчеты в зависимости от выбранного типа расчетов с использованием интерфейса delete transact; { QMutexLocker locker(&mutex); if (transactions.isEmpty()) emit allTransactionsDone(); } }}
connect(&thread, SIGNAL(transactionStarted(const QString &)), statusBar(), SLOT(showMessage(const QString &)));
Run::Run(){//теперь пустой}void TransactionThread::run() //теперь вот такой{ Transaction *transact = 0; forever { { QMutexLocker locker(&mutex); if (transactions.isEmpty()) transactionAdded.wait(&mutex); transact = transactions.dequeue(); if (transact == EndTransaction) break; // oldImage = currentImage; } emit transactionStarted(transact->message());///////////////////// положил вот сюда//////////////// //в этой функции будем выполнять долгие расчеты, при этом интерфейс приложения зависать не должен, а он зависает....!!! int i=1; int a = 10; while (a !=i){ a=a/i; i++; }//вывожу на интерфейс значения счетчика//QString str;str = QString::number(i,10);emit transactionRun(str) delete transact; { QMutexLocker locker(&mutex);// currentImage = newImage; if (transactions.isEmpty()) emit allTransactionsDone(); } }}
//вывожу на интерфейс значения счетчика//.....emit transactionRun(str)
void QThread::run () [virtual protected]The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec().You can reimplemented this function to do other useful work. Returning from this method will end the execution of the thread.---------int QThread::exec () [protected]Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().It is necessary to call this function to start event handling.See also quit() and exit().
QString Run::apply(const QString &str){ QString str2; //непосредственно расчеты int i=1; int a = 10; while (a !=i){ a=a/i; i++; str2 = QString::number(i,10); }return (str2);}
emit allTransactionDone();