c++qttimerqtimerqlcdnumber

Qt QLCDNumber issue


I am making a timer/stopwatch with Qt Creator. But, my reset function (reset button clicked) is not working as I want it to. I want it to stop the timer and set the display (QLCDNumber) to 0. Instead, the timer is stopped but the display numbers stay the same as if the pause button was clicked. Except that when the timer is started (start button clicked) again, it restarts from the original time (as I want it to do). Here is the code.

I only included the parts that are part of the problem.

void MainWindow::delay()
{
    QTime dieTime = QTime::currentTime().addSecs(1);
    while (QTime::currentTime() < dieTime && !spause && !sreset)
    {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}

void MainWindow::on_tstart_clicked()
{
    ttime = treset ? 0 : ttime;
    tpause = treset = false;
    ttime = ttime == 0 ? (ui->hr->value() * 3600 + ui->min->value() * 60 + ui->sec->value()) : ttime;
    while (ttime >= 0 && !tpause && !treset)
    {
        const unsigned short sec = ttime % 3600 % 60, min = ttime % 3600 / 60, hr = ttime / 3600;
        ui->tsec2->display(sec % 10);
        ui->tsec1->display(sec / 10);
        ui->tmin2->display(min % 10);
        ui->tmin1->display(min / 10);
        ui->thr2->display(hr % 10);
        ui->thr1->display(hr / 10);
        delay();
        if (!tpause && !treset) --ttime;
    }
}

void MainWindow::on_tpause_clicked()
{
    tpause = true;
}

void MainWindow::on_treset_clicked()
{
    treset = true;
    ui->ssec2->display(0);
    ui->ssec1->display(0);
    ui->smin2->display(0);
    ui->smin1->display(0);
    ui->shr2->display(0);
    ui->shr1->display(0);
}

Solution

  • Your click on a button is processed only in the function delay() containing processEvents(). When delay() is executed, it sends message to the application, but on_treset_clicked() is executed after the next loop of while() was started. Use QTimer to avoid this situation.

    Here is how to use QTimer in your case.

    (mainwindow.h)
    #include <QTimer>
    ...
    QTimer timer;
    
    (mainwindow.cpp)
    
    MainWindow::MainWindow()
    {
        ...
        connect(&timer,SIGNAL(timeout()),this,SLOT(on_timer()));
    }
    
    void MainWindow::on_tstart_clicked()
    {
        timer.start(1000);
    }
    
    
    void MainWindow::on_timer()
    {
        if(timer.isActive()) return;
        ttime--;
        (display LCD values)
        if(ttime<=0) 
        {
            ttime=0;
            (emit signal for alarm or whatever you want)
            timer.stop();
        }
    }
    
    void MainWindow::on_tpause_clicked()
    {
        timer.stop();
        (display LCD values)
    }
    
    void MainWindow::on_treset_clicked()
    {
        timer.stop();
        ttime=0;
        (display zeroes)
    }