PDA

View Full Version : set progress bar values inside a thread



ruben.rodrigues
28th May 2011, 14:09
Hi all!

I wrote a progress bar class that has a Gui part and a thread part. In the way I have now the thread has a "for" loop that emits a signal to the Gui class and then has a 100ms sleep.

This works but the gui kinda frezzes so I was trying to implement it in another way.
I want to send the progress bar object to the thread class and set the value from there. When I tried this the programm crashed and I need some help.

here the code:


#include "progressbar.h"

class SleepThread : public QThread
{
public:
static void mySleep(int nMSecs)
{
msleep(nMSecs);
}
};


progressBar::progressBar(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
}

progressBar::~progressBar()
{

}

void progressBar::changeMessage(QString text){ //this is where I update the message from my main gui
ui.label->setText(text);
}

void progressBar::init(){ //this is to open and show the progress bar
this->show();
pbarThread = new barThread;
pbarThread->setProgressBar(ui.progressBar); //set the progress bar pointer
connect(pbarThread, SIGNAL(setValue(int)), this, SLOT(setPBarValue(int)));
pbarThread->start();
}

void progressBar::setPBarValue(int i){ //this is how I set the value but I don't want to use this function anymore
ui.progressBar->setValue(i);
if(i == 100){
if(ui.progressBar->invertedAppearance()){
ui.progressBar->setInvertedAppearance(false);
}else{
ui.progressBar->setInvertedAppearance(true);
}
}
}

void progressBar::stopPBar(){ //to stop the thread before I delete the object
this->hide();
pbarThread->stopThread();
while(!pbarThread->isFinished()){
//Wait on loop until thread is finished
}
}

void barThread::stopThread(){
running = false;
}

void barThread::run(){

running = true;

while(running){
for(int i = 0; i < 101; i=i+5){
_progressBar->setValue(i); //This is where it crashes now
// emit setValue(i); //the signal I emited before to alert the Gui class
if(!running) break;
SleepThread::mySleep(100);
}
}
}



#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H

#include <QtGui>
#include "ui_progressbar.h"
#include <QtCore>
#include <qthread.h>

class barThread : public QThread
{
Q_OBJECT

public:
bool running;
void stopThread();
void setProgressBar(QProgressBar *pb){_progressBar = pb;}

protected:
void run();

private:
QProgressBar *_progressBar;

signals:
void setValue(int);
};

class progressBar : public QDialog
{
Q_OBJECT

public:
progressBar(QWidget *parent = 0);
~progressBar();

void init();
void stopPBar();
void changeMessage(QString);

private slots:
void setPBarValue(int);

private:
Ui::progressBarClass ui;

barThread *pbarThread;
};

#endif // PROGRESSBAR_H

I already did once a class that showed a live picture from a thread and the method was the same.

Thanks in advance

DanH
28th May 2011, 14:52
1) Why do you have mySleep in a separate class? It just confuses things?

2) Why are you using sleep rather than a repetitive timer? (Then you wouldn't even need a separate thread.)

3) You should probably use Qt::QueuedConnection for the 5th parm of connect(). It should be defaulting to that, but it doesn't hurt to be specific.

Lykurg
28th May 2011, 14:55
All GUI stuff has to be in the main thread. Also accessing GUI parts from a custom thread is a very bad idea. So your signal/slot connection is the right thing to do. If it was freezing, then you probably called the thread function in a wrong way.