PDA

View Full Version : Display arrray values in QLCDNumber



sharofiddin
25th March 2019, 17:42
I am working on a math trainer project. So, I must display int values from the array to QLCDNumber with delay. I used QTimer::singleshot but it delays only before the first number. Here is my code. What is the problem?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLCDNumber>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_pushButton_clicked()
{
int arr[] = {100,2,21,12};
for (int i = 0;i<4;i++) {
QTimer::singleShot(2000,this,[=]{
ui->lcdNumber->display(arr[i]);
});
}
}


I can see only 12.13059

d_stranz
25th March 2019, 21:07
Your on_pushbutton_clicked() slot fires four single shot timers in very quick succession, so essentially all of them execute their timeout events at the same time (maybe a fraction of a millisecond apart). Once the for() loop completes and the clicked slot exits, these four timeouts execute too fast for you to see, so the only number visible is the last one. You need to refactor the application so that only one timer is running, and when it times out, it starts a new timer to display the next number.

Your mistake is in thinking QTimer::singleShot() acts as a delay. It doesn't - all it does is schedule something to happen later, then exits.

One way to refactor might be to make the QTimer a member of the MainWindow class (instead of a single-shot). Also make the number array a member of MainWindow, and add a "current index" variable. I would turn the lambda into an actual slot in the MainWindow class.

The clicked slot needs to: 1) set the current index to 0, 2) disable the button, and 3) start the QTimer
The timeout slot needs to: 1) display the number at the current index, 2) increment the index, and 3) if the index == array size, enable the button else start the QTimer again.

With this refactoring, all the clicked slot does it start the first timer and exit, so the UI stays alive. To prevent the user from clicking the button while the display is stepping through the array, the button is disabled until the end of the array is reached, at which point it is enabled and can be clicked again to start over.

anda_skoa
26th March 2019, 06:51
Another recommendation: don't use the "connect by name" feature to connect signals of widgets in the designer form to slots.

Use actual, explicit connect() calls.

Gives you much more robust and maintainable code

Cheers,
_