Disabling a button while a task is in execution
-
wrote on 24 Sept 2013, 17:54 last edited by
Hello all,
my problem is in the following@
...
connect(startButton,SIGNAL(clicked()),this,SLOT(execVQA()));
...void MainDialog::execVQA()
{
startButton->setEnabled(false);
task(); // do time-consuming something
//startButton->setEnabled(true);
}
@But the startButton is only disable when task() is finished.
I have read many alternatives for this problem, such as add QCoreApplication::processEvents() before task() or startButton->repaint(), but they do not have any effect.I'm sorry for my unsatisfactory english.
Thanks a lot and all the best. -
wrote on 24 Sept 2013, 18:22 last edited by
Processing the events should work. You could also add a second slot that you connect to before you make the other connection.
@connect(startButton, SIGNAL(clicked()), this, SLOT(deactivateThatButton());@
Maybe it would be a better solution if you were using a second thread for the task?
-
wrote on 24 Sept 2013, 19:07 last edited by
I tried your first suggestion but it does not have effect.
I'm reading about threads.
Thanks. -
wrote on 24 Sept 2013, 20:52 last edited by
I tried this:
@
connect(startButton,SIGNAL(clicked()),this,SLOT(execVQA()));
...void MainDialog::execVQA() {
bool stop = false;
startButton->setEnabled(false);
thread.start(); // the task() is in run();
while(!stop) {
if(thread.isFinished()) {
stop = true;
startButton->setEnable(true);
}
}
}
@
but without sucess. It has the same effect of the first code. -
wrote on 24 Sept 2013, 21:09 last edited by
That is the wrong way to use a thread, and of course your application is blocked: It is running the while-loop while your task is being worked on. And that loop should push a CPU-core to its limits, at least the way you are using it. There is no room to update the UI.
How and where exactly did you try to use qApp->processEvents(QEventLoop::AllEvents) ? Maybe you put it in the wrong place?
-
wrote on 24 Sept 2013, 22:21 last edited by
Initially a tried this
@
...
connect(startButton,SIGNAL(clicked()),this,SLOT(execVQA()));
...void MainDialog::execVQA()
{
disableActions(); // disable startButton and others
QApplication::processEvents(QEventLoop::AllEvents);
task(); // a time-consuming activity
finishMessage(); // display a finish message
enableActions(); // enable startButton and others
}
@
but it does not work as I said.Thanks.
-
wrote on 25 Sept 2013, 04:27 last edited by
Well, maybe give "this":http://qt-project.org/doc/qt-5.1/qtcore/qcoreapplication.html#processEvents-2 a shot instead:
@qApp->processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 2000);@I really don't see why that shouldn't work, sorry.
-
wrote on 25 Sept 2013, 05:50 last edited by
Thanks a lot. I will try others alternatives and if I accomplish I post here.
-
wrote on 25 Sept 2013, 06:36 last edited by
Hi,
think you need to study the tread stuff a bit further! When you have a very time consuming task, but the gui may not 'hang' it's the best solution to get that done.
Maybe read this post:
"Threads done right":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
The woman really knows here stuff ;-)
Greetz -
wrote on 25 Sept 2013, 17:21 last edited by
Thanks a lot for the tip =D
-
wrote on 26 Sept 2013, 18:47 last edited by
Maybe you don't need threads at all... just analyze the situation and you'll probably get a better alternative. From my point of view you just need to disable the button before running the time-consuming task. Usually people wants a nice disable behavior for any of these tasks:
-> A time-consuming task to be run only once.
In this situation you don't want the user to be able to press a "start" button multiple times as this would screw up the application by starting many times the same time consuming task.
Solution: when the button reports a clicked event, just disable it and start the time consuming task right after. Then re-enable the button.
-> A timeout behavior.
In this situation you want a "check" button to be disabled for some time and re-enabled after a timeout. This behavior is often wanted for Updates checking.
Solution: when the button is pressed disable it, then start a timer with your time-out, and start the time consuming task (or any other) right after. When the timer reports a finished event, re-enable the button by answering the timer event with a SLOT.This is what I think is most common to be found in applications and can be implemented without threads or concurrent tasks.
1/11