Qt QLCDNumber issue

1k Views Asked by At

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);
}
3

There are 3 best solutions below

2
On BEST ANSWER

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)
}
0
On

(Posted on behalf of the OP).

Everything is solved! I was resetting the stopwatch display by accident. Thanks @Michael!

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // ttimer was declared in "MainWindow" -> QTimer ttimer;
    connect(&ttimer, SIGNAL(timeout()), this, SLOT(on_timer()));
}
void MainWindow::on_tstart_clicked()
{
    ttime = ttime == 0 ? (ui->hr->value() * 3600 + ui->min->value() * 60 + ui->sec->value()) : ttime;
    ttimer.start(1000);
}

void MainWindow::on_timer()
{
    if (!ttimer.isActive()) return;
    --ttime;
    const unsigned short hr = ttime / 3600, min = ttime % 3600 / 60, sec = ttime % 60;
    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);
    if (ttime <= 0)
    {
        // (emit signal for alarm or whatever you want)
        ttimer.stop();
    }
}

void MainWindow::on_tpause_clicked()
{
    ttimer.stop();
    // (display LCD values)
}

void MainWindow::on_treset_clicked()
{
    ttimer.stop();
    ttime = 0;
    ui->tsec2->display(0);
    ui->tsec1->display(0);
    ui->tmin2->display(0);
    ui->tmin1->display(0);
    ui->thr2->display(0);
    ui->thr1->display(0);
}
0
On

I implemented QTimer in my code, but when I press the "Start" button (on_tstart_clicked) or any other buttons, nothing happens (no change in display).

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // ttimer was declared in "MainWindow" -> QTimer ttimer;
    connect(&ttimer, SIGNAL(timeout()), this, SLOT(on_timer()));
}
void MainWindow::on_tstart_clicked()
{
    ttime = ttime == 0 ? (ui->hr->value() * 3600 + ui->min->value() * 60 + ui->sec->value()) : ttime;
    ttimer.start(1000);
}

void MainWindow::on_timer()
{
    if (!ttimer.isActive()) return;
    --ttime;
    const unsigned short hr = ttime / 3600, min = ttime % 3600 / 60, sec = ttime % 60;
    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);
    if (ttime <= 0)
    {
        // (emit signal for alarm or whatever you want)
        ttimer.stop();
    }
}

void MainWindow::on_tpause_clicked()
{
    ttimer.stop();
    // (display LCD values)
}

void MainWindow::on_treset_clicked()
{
    ttimer.stop();
    ttime = 0;
    ui->ssec2>tsec2->display(0);
    ui->ssec1>tsec1->display(0);
    ui->smin2>tmin2->display(0);
    ui->smin1>tmin1->display(0);
    ui->shr2>thr2->display(0);
    ui->shr1>thr1->display(0);
}

The issue was simple, but I kept glossing over it. I had to change ttimer.isActive() to !ttimer.isActive().

But, now the the reset (on_treset_clicked) doesn't work. The QLCDNumber's aren't reset to 0.