[Qt] Program z wątkiem wykrzacza się po uruchomieniu

0

Witam,
Napisałem program-benchmark obliczający ile mniej więcej zabierze czasu rozwiązanie problemu Wież Hanoi dla podanej przez użytkownika liczby krążków. Użyłem gotowego w internecie rekurencyjnego algorytmu i wszystko działało poprawnie. Napisałem ładne GUI przy pomocy Qt 4.3.3 dla Windowsa (choć ten sam pod skompiluje się pod Linuksem). Wszystko było wyliczone pięknie i ładnie wyświetlone oprócz jednego mankamentu. QProgressBar miał nieco opóźniony zapłon. To znaczy dopiero gdy program się wykonał to nagle wskakiwał na 100% choć wyraźnie zaznaczyłem aby postęp się zwiększał przy każdym obliczeniu. Postanowiłem, że po prostu program się wiesza i powinienem puścić obliczenia na osobny wątek. Skorzystałem więc z klasy QThread, czego jeszcze nigdy w życiu nie robiłem (świeży jestem w Qt). Długo poprawiałem błędy przy kompilacji aż w końcu uzyskałem plik EXE. Jednak po uruchomieniu program od razu
się wyłącza i mam komunikat, że "Aplikacja została zamknięta". Skorzystałem z qDebug() do wypisywania tego, co się aktualnie dzieje, ale program nic nie drukuje na standardowe wyjście w konsoli (a uruchamiam go z cmd). Nie wiem czy mogę wkleić 4 pliki źródłowe programu ale nie są one za długie to chyba nic się nie stanie (nikt nie umarł od ponad 200 linii kodu :P)

Plik qhanoimark.h

/***************************************************************************
 *   Copyright (C) 2008 by Bartosz Dolewski  
 *   E-mail: [email protected]   
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef QHANOIMARK_H
#define QHANOIMARK_H

#include <QtGui>
#include <QMessageBox>
#include <QString>
#include <QMainWindow>
//#include <QDebug>
#include "ui_qhanoimark.h"
#include "qhanoithread.h"

using namespace Ui;
class QHanoiMark : public QDialog
{
 Q_OBJECT
	public:
		QHanoiMark(QWidget *parent = 0, Qt::WFlags f = 0);
	       ~QHanoiMark(){};
		
	private slots:
		void incrementMoves(int newMove);
		void do_benchmark();
		void about_program();
	
		
	private:
		void createMenu();
		//void hanoi(int src, int dst, int n);
		Dialog ui;
		QHanoiThread*  myThread;
		int QHMdiscs, QHMmoves;
		QMenu *about_menu;
		QMenuBar *mBar;
		QAction *aboutAuthor, *aboutLibs;
		 
};
#endif

Plik qhanoimark.cpp

/***************************************************************************
 *   Copyright (C) 2008 by Bartosz Dolewski  
 *   E-mail: [email protected]   
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "qhanoimark.h"

QHanoiMark::QHanoiMark(QWidget *parent, Qt::WFlags f): QDialog(parent,f)
{
  qDebug()<<"Program has started \n";
  ui.setupUi(this);
  QTextCodec::setCodecForTr(QTextCodec::codecForName ("UTF-8"));

  setWindowTitle("QHanoiMark");
  ui.progressBar1->setMinimum(0);
  ui.progressBar1->setMaximum((2 << QHMdiscs) - 1);
  //just for beginning
  ui.progressBar1->setValue(0);
  //building menubar
  
  QHanoiMark::createMenu();
  
  qDebug()<<"Creating connections.....";
  connect(aboutAuthor    , SIGNAL(triggered())         , this           , SLOT(about_program()));
  connect(aboutLibs      , SIGNAL(triggered())         , qApp           , SLOT(aboutQt())      );
  connect(ui.pushButton1 , SIGNAL(clicked())           , this           , SLOT(do_benchmark()) );
  connect(myThread       , SIGNAL(progressChanged(int)), ui.progressBar1, SLOT(setValue(int))  );
  connect(myThread       , SIGNAL(movesChanged(int))   , this           , SLOT(incrementMove(int)));
  connect(myThread       , SIGNAL(textChanged(const QString & )), ui.textEdit1, SLOT(append(const QString&)));
  qDebug()<<"\t[+] Done\n";
}

void QHanoiMark::do_benchmark()
{
	ui.progressBar1->reset();
	ui.textEdit1->clear();
    bool ok;
    QHMmoves = 0;
	QHMdiscs = ui.lineEdit3->text().toInt(&ok,10);
    QTime time(0,0,0,0);
	QTime endOfTime(0,0,0,0);
	time.start();
	
	//starting computing
	//hanoi(1,3,discs);
	myThread = new QHanoiThread(1,3, QHMdiscs);
	myThread->start();
	endOfTime = endOfTime.addMSecs(time.elapsed());
	
	//setting a lineEdit with time
	ui.lineEdit1->setText(endOfTime.toString("hh:mm:ss.zzz"));
	//ui.lineEdit2->setText(QString::number(moves,10));
}

void QHanoiMark::about_program()
{
 QMessageBox::information(this, tr("About program"), tr("This application was written by Bartosz Dolewski"));
}

void QHanoiMark::createMenu()
{

  mBar = new QMenuBar(this);
 
  aboutAuthor = new QAction(tr("About program"), this);
  aboutAuthor->setStatusTip(tr("Display short informations about author"));
  mBar->addAction(aboutAuthor);
 
  
  aboutLibs = new QAction(tr("About Qt"), this);
  aboutLibs->setStatusTip(tr("Display informations about Qt library"));
  mBar->addAction(aboutLibs);
}

void QHanoiMark::incrementMoves(int newMove)
{
 ui.lineEdit2->setText(QString::number(QHMmoves,10));
}

A teraz plik z moją implementacją wątków (tak jak mi Qt Assistant nakazał):
Plik qhanoithread.h

 #ifndef QHANOITHREADS_H
#define QHANOITHREADS_H
#include <QThread>
#include <QString>

class QHanoiThread: public QThread
{
 Q_OBJECT
	signals:
		void progressChanged(int newvalue);
		void textChanged(const QString &descMove);
		void movesChanged(int moves);
 public:
		QHanoiThread(int src, int dst, int n);
		virtual ~QHanoiThread(){};
		void run();
 private:
	void hanoi(int a, int b, int c);
	int mySrc; //number of pine, which we would start(for example  1 == first pine, 2 == second pine etc)
	int myDst; //number of pine, which we would finish
	int myN;   //numbers of discs
	QString desc;
	int move;
};
#endif

No i na sam koniec już Plik qhanoithread.cpp

#include "qhanoithread.h"
QHanoiThread::QHanoiThread(int src, int dst, int n): mySrc(src), myDst(dst), myN(n)
{
}

void QHanoiThread::run()
{	
 QHanoiThread::hanoi(mySrc, myDst, myN);
}
void QHanoiThread::hanoi(int a, int b, int c)
{ 
   int helper = 6 - (mySrc + myDst);   // calculate helper

   if (myN == 1)
   {
	  //ui.textEdit1->append(QString::number(src,10) + " ===> " + QString::number(dst,10));
	  desc = QString::number(mySrc,10) + " ===> " + QString::number(myDst,10);
	  move++;
	  emit textChanged(desc);
	  emit movesChanged(move);
	  emit progressChanged(move);
	  //ui.progressBar1->setValue(moves);
   }
   else
   {

      QHanoiThread::hanoi(mySrc, helper, myN-1);
      QHanoiThread::hanoi(mySrc, myDst, 1);
      QHanoiThread::hanoi(helper, myDst, myN-1);
   }
   exec();
}

Koniec końców program działa bardzo dobrze, jeśli chodzi o jego cel w którym został powołany tylko teraz sprawa kosmetyki bo QProgressBar nieźle psuje efekt :) Zgłaszajcie nawet najgłupsze pomysły bo ja nie mam pojęcia co tutaj może być źle.

0

QProgressBar jak i cała reszta w Qt jest dość prosta :)

ui.progressBar1->setMaximum((2 << QHMdiscs) - 1);
to twoje maksimum progress bar'u

jedyne co musisz zrobić (nie chce mi sie analizować kodu a także bym musiał sobie przypomnieć problem wież )
to w momencie w którym wykonywany jest jeden ruch z tych 2 << QHMdiscs) - 1 całościowych
w tym momencie musisz dać ui.progressBar1->setValue(nr wykonywanego ruchu)
dzięki temu powiesz mu w którym momencie dokładnie jestes :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1