Disabling a button while a task is in execution



  • 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.



  • 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?



  • I tried your first suggestion but it does not have effect.
    I'm reading about threads.
    Thanks.



  • 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.



  • 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?



  • 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.



  • 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.



  • Thanks a lot. I will try others alternatives and if I accomplish I post here.



  • 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



  • Thanks a lot for the tip =D



  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.