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.