Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

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