[Solved] Random number generator with a time interval



  • Hello,

    I am new to this forum and still pretty new at using the Qt program, so please be patient with me. I am working on a program that after a certain amount of time a new random number appears on the GUI. How I want it is that when a button is pressed within the GUI, the random number generator starts and displays its first random number. Once a certain amount of time has passed (lets say 15 secs), a new random number is then displayed within the GUI. I have gotten a suggestion of using a timer interrupt within the program, but I am having a hard time finding a decent example of it. I am not an advanced programmer, so please once again, be patient with me. I really do appreciate all the help. Thank you very much for any type of advice.


  • Moderators

    Hi and welcome to DevNet.

    What you need is a "QTimer":http://qt-project.org/doc/qt-5/QTimer.html#details, and a slot in your class that will regenerate a number. For basic random number generation, you can use "qRand":http://qt-project.org/doc/qt-5/qtglobal.html#qrand.

    If anything is still unclear, please ask :)



  • Thank you for the advice. I have been looking into the QTimer function for a while today and I am still confused on how to use the "connect(timer,SIGNAL(timeout()),this,SLOT())" function. The main part about it is I am unsure about what I need to put in the "SLOT" section. I would like my GUI to have it when the button is pressed the first random number is displayed on the label, then a certain amount of time goes by, then another random number is displayed. The only way to get out of that loop is by clicking the button again. That is why I thought I would have to put clicked() for the SLOT section. But it did not work. A message would come up saying no such slot MainWindow::clicked() in...


  • Moderators

    Slot is a method you create yourself in your code (although, of course, some Qt classes have some convenient slots prepared) that reacts to a signal in a way you desire. A detailed description can be found "here":http://qt-project.org/doc/qt-5/signalsandslots.html but it can be hard to grasp for a newbie. I'll try to explain it in a bit simpler manner.

    So, your QTimer will emit a signal (timeout) every few seconds. What you want to do is to then get a new random number, and update the label. To achieve this, you should add a slot in your code:
    @
    // MainWindow.h
    private slots:
    void updateRandomNumber();
    // your timer:
    QTimer timer;

    // MainWindow.cpp
    void MainWindow::updateRandomNumber()
    {
    ui->myLabel->setText(QString::number(qRand()));
    }

    // signal and slot connection. You probably do it in your button clicked slot
    void MainWindow::on_pushButton_clicked()
    {
    if (timer.isActive()) {
    timer.stop(); // timer will stop if you click the button again
    } else {
    connect(&timer, SIGNAL(timeout()), this, SLOT(updateRandomNumber()));
    timer.start(1000);
    }
    }
    @



  • I will defiantly try this. I was getting confused on where I should put the information for the QTimer class. I was putting that information in my .cpp instead of my .h. In doing that, does that answer the question into why the "redefinition" and "previous" class type errors kept on popping up every time I would build my GUI?


  • Moderators

    I don't know. I have not seen your code, or the errors you mention. I can guess if you want me to ;)



  • I will first add your suggestions into my code. If I am still having trouble, I will post my code on there. Please do not laugh or judge me too much on it when you see it. I am not a pro at programming. Please be patient with me. Once again, thank you so much for giving me pointers when dealing with this code.


  • Moderators

    Hey, don't worry! :-) I may be harsh at times, but I do understand that you are learning and everything is tricky for you. I used to be a newbie, too.



  • I have input your suggestions in my mainwindow.h file and mainwindow.cpp, but every time I click the pushButton the first time, the GUI exits unexpectedly instead of start the RNG. Below is my code:
    @//mainwindow.h
    namespace Ui
    {
    class MainWindow;
    }

    class MainWindow:public QMainWindow
    {

    Q_OBJECT

    public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

    private slots:

    void on_pushButton_clicked();

    void updateRandomNumber();

    private:

    Ui::MainWindow *ui;

    QTimer *timer;

    };

    #endif // MAINWINDOW_H

    //MainWindow.cpp

    MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

    {

    ui->setupUi(this);

    ui->max->setValidator(new QIntValidator(0,100000000));

    ui->min->setValidator(new QIntValidator(0,100000000));

    }

    MainWindow::~MainWindow()

    {

    delete ui;
    }

    void MainWindow::updateRandomNumber()

    {

    int high = ui->max->text().toInt();

    int low = ui->min->text().toInt();

    qsrand((unsigned)time(0));

    ui->label->setText(QString::number(qrand()%((high + 1) - low) + low));

    }

    //Control timer with the pushButton. RNG should activate.

    void MainWindow::on_pushButton_clicked()
    {
    if(timer->isActive())

    {

    connect(timer,SIGNAL(timeout()),this,SLOT(updateRandomNumber()));

    timer->start(15000);

    }

    else

    {

    timer->stop();//timer will stop if you click button again.

    }

    }
    @

    At first I kept your suggestion and had the "connect" function after the else statement, but it was still exiting out the program unexpectedly. I wanted the user to input their min and max value within the GUI and the random values stay within those values. Do you have any suggestions on why it keeps kicking me out of the GUI after I press the pushButton? Thank you once again for your help.



  • Okay, I did a practice code on getting the timer and random number generator to be in sync. That came out fine. Once the pushButton is pressed, the RNG starts with the delay timer I asked for, but after I press the button again, it does not want to stop the RNG even though I have the disconnect command inputted in my code. Any suggestions on why this is would be lovely :) Below is my code. Thank you once again for your help Mr. sierdzio.

    @
    //mainwindow.cpp
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "cstdlib"
    #include "stdlib.h"
    #include "string"
    #include "QTimer"
    #include "QObject"

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

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

    void MainWindow::updateRandomNumber()
    {
    qsrand((unsigned)time(0));
    ui->label->setText(QString::number(qrand()));
    }

    void MainWindow::on_pushButton_clicked()
    {
    QTimer *timer = new QTimer(this);
    if(timer->isActive())
    {
    QObject::disconnect(this,SLOT(updateRandomNumber(void)));
    //delete updateRandomNumber;
    timer->stop();//timer will stop if you click the button again.
    }
    else
    {
    connect(timer,SIGNAL(timeout()),this,SLOT(updateRandomNumber()));
    timer->start(1000);
    }
    }

    @


  • Moderators

    You have not initialised the timer, so the program segfaults. You declare it as a pointer, but newer call this:
    @
    timer = new QTimer;
    @

    The best place to do it is the constructor. A decent compiler should have warned you about this, too.


  • Moderators

    Oh, it seems we have been writing a post in parallel :)

    You are initialising the timer in wrong place! Every time you click a button, you create a new QTimer. This is a bad memory leak, and will not work as intended. Move the initialisation to the constructor:
    @
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    QTimer *timer = new QTimer(this);
    }
    @



  • when I moved it to
    @
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    QTimer *timer = new QTimer(this);
    }
    @

    It would exit out of the GUI unexpectedly after I push the pushButton. But once it is back under

    @
    void MainWindow::on_pushButton_clicked()
    {
    QTimer *timer = new QTimer(this);
    @

    The GUI does not exit out, the RNG timer works after I press the pushButton for the first time, but the RNG timer will not stop once the pushButton is pressed for a second time. Thank you for your help and your patience. It is greatly appreciated.


  • Moderators

    Sorry, I made a small mistake. My previous snippet should have been:
    @
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    timer = new QTimer(this);
    }
    @

    As you see, no "QTimer *". This is because we want to initialise the timer present in the header file, and not a completely new one. You can also move the connect statement to the constructor, and remove the disconnect statement - it should still work correctly.



  • IT WORKS!!!! thank you so much. I am going to add some stuff to my GUI and I have a feeling you will be hearing from you again lol. Thank you once again for your help.


  • Moderators

    You are welcome, I'm glad to hear it works. Happy coding!



  • @
    Line 82 (qrand()%((high + 1) - low) + low) )
    @

    Is not a very good method to generate random numbers within a given range. (In fact it's very very bad for most generators )

    You are assuming that the low-order bits from the generator are uniformly distributed . This is not the case with most generators. In most generators the randomness occurs in the high order bits.

    By using the remainder after divisions you are in effect throwing out the randomness.

    You should scale using multiplication and division. Not using the modulo operator.
    eg
    @
    my_number= start_required + ( generator_output * range_required)/generator_maximum;

    if generator_output is in [0, generator_maximum]
    my_number will be in [start_required , start_required + range_required]
    @


Log in to reply
 

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