PDA

View Full Version : Need some help about QProgressbar while using QThread



qzb1111
31st July 2007, 09:38
My application is to do some file operations.You know while processing file of large size ,the application looks as if it is dead.So I put all my works into QThread like this:


class MainOperation:public QThread
{
Q_OBJECT
....
public slots:
virtual void run()
{
FileWriter fw1(_errorFile);
FileReviser fr(_templateFile);
fw1.appendReviser(&fr);
emit fileSizedRecognized(fw1.GetFileSize());
while(!fw1.IsOK())
{
fw1.save(_outputFile);
emit posChanged(fw1.GetPos());
}
emit finished();
}
signals:
void fileSizedRecognized(int fileSize);
void posChanged(int pos);
void finished();
}


Then I want these signals to be sent to My UI Form then update the position of the progressbar like this(below are slots in my UI Form):


public slots:
void prepareFile(int fileSize)
{
pushButton_Begin->setEnabled(false);
pushButton_end->setEnabled(false);
_fileSize=fileSize;
progressBar->setTotalSteps(100);
}
void setProgressBarPos(int pos)
{
progressBar->setProgress(pos/_fileSize*100);
}
void finish()
{
pushButton_end->setEnabled(true);
}

But it doesn't work.These slots are fired but the ProgressBar's position is always zero.Below is code fragments in main.cpp


Ui::Form ui;
ui.setupUi(&w);
ui.label_ErrorFile->setText(sErrorFile);
ui.label_TemplateFile->setText(sTemplateFile);
ui.label_OutputFile->setText(sOutputFile);
MainOperation mainOp(sErrorFile,sTemplateFile,sOutputFile);
QObject::connect(ui.pushButton_Begin,SIGNAL(clicke d()),&mainOp,SLOT(start()
));
QObject::connect(&mainOp,SIGNAL(fileSizedRecognized(int)),&ui,SLOT(prepareF
ile(int)));
QObject::connect(&mainOp,SIGNAL(posChanged(int)),&ui,SLOT(setProgressBarPos
(int)));
QObject::connect(&mainOp,SIGNAL(finished()),&ui,SLOT(finish()));
QObject::connect(ui.pushButton_end, SIGNAL(clicked()), &app, SLOT(quit()));

I was really confused,expecting your help.Thanks!

marcel
31st July 2007, 09:59
Have you edited by any chance the code generated by UIC?
For example, the UI::Form class. This is not ok, because it will get overwritten each time you modify the ui file.

Also, why are you using Q3ProgressBar?

My guess is that the progress bar always is at 0 because the file pos always comes 0, therefore pos/_fielSize*100 = 0;

Are you sure all values are ok?

Regards

qzb1111
31st July 2007, 14:00
Thank you for your replay.
I have done something to debug my code,it did work well but the postion of progress bar did not change.It looks as if the event is not fired until the thread ends.I have ever used QProgressbar,while Q3Progressbar is my secondary chioce.
I have also tried app->processEvents every time the MainObject emit the signal,but it is of no help.Maybe QCustomEvent is the only way?

marcel
31st July 2007, 14:05
Another thing: in QThread, run is not a public slot.
run() is virtual protected in QThread so you should defined as such.


The code look OK, although you should choose one of the "standard" coding styles, i.e. implement the methods in cpp files, not inline( this is more like java ).

Try switching the visibility of run. That could have been the problem.
Emitting a signal from a thread is OK, no need for custom events.

Regards

qzb1111
31st July 2007, 15:50
Now everything gose well.Besides the visibility problem ,there is another mistake.That is the signal should be sent to the progressbar directly.I sent the signal to my UI Form and the UI Form call setvalue() or setprogress() to change the position of progressbar.This is a invalid operation.
Thank you,marcel!

marcel
31st July 2007, 15:52
Now everything gose well.Besides the visibility problem ,there is another mistake.That is the signal should be sent to the progressbar directly.I sent the signal to my UI Form and the UI Form call setvalue() or setprogress() to change the position of progressbar.This is a invalid operation.
Thank you,marcel!

You're welcome, but having the form class as proxy is not a bad idea so you should stick to it.

Although the signal is posted as an event for the progress bar, worker threads shouldn't work directly with widgets.

Regards