Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTimer - Problem when passing with passing the values



  • Hi,
    I am a new at Qt. I am facing the problem with QTimer and after hours of studying Qdocumentation and days of trying to figure out I am conufsed. I've search all the topics of QTimer on this forum, but I did not find the answer. So here it is:
    I am currently using a Qt 5.12.0 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit
    my OS is Linux mint. I have a problem when I am passing a variable provided in Gui (qml) to Qtimer in C++. When i provide let say 5s to timer's interval it works, then I am passing 1s and it also works good, but when I provide 5s the timer still works like the 1s was provided. When I use set singleshot(true) the problem does not occur. Here is the code :

    c++:
    void DTimer::timeIn(QString Time)
    {
    qDebug()<<"Timer's time :"<<Time;
    iTime=Time.toInt()*1000;
    timer=new QTimer(this);
    if(iTime>0){
    timer->start(iTime);

    connect(timer, SIGNAL(timeout()),
            this, SLOT(timerOut()));
    }
    

    }

    qml

    TextField{id:timeSet
    anchors.centerIn: zadanyCzas
    width: 40
    height: 20

                                             onTextChanged: obtainTime.getData(timeSet.text);
                                            }

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You are recreating a new timer each time you call timeIn which is likely not what you want. Unless it supposed to be a single shot timer ?



  • I've created a class and this timeIn is a method. Do you know what should I do to make it works wright. You're right I don't want it to be a single shot timer. I'd like it to be something like in plc timer.


  • Lifetime Qt Champion

    @DdsS please show your whole code. the problem is likely outside these fragments.


  • Lifetime Qt Champion

    Make your QTimer object a member of your class and only call start with the new value.



  • header:
    #ifndef DTIMER_H
    #define DTIMER_H
    #include <QObject>
    #include <QString>
    #include <QDebug>
    #include <QTimer>
    class DTimer : public QObject
    {
    Q_OBJECT

    public:
    Q_PROPERTY(QString sTime MEMBER sTime NOTIFY timeChanged)
    explicit DTimer(QObject *parent = nullptr);

    QTimer *timer;
    QString sTime;
    

    signals:
    void timeChanged();

    public slots:
    void timerOut();
    void timeIn(QString Time);

    private:

        int iTime;
    

    };

    #endif // DTIMER_H

    source:
    #include "DTimer.h"

    DTimer::DTimer(QObject *parent) : QObject(parent)
    {
    }

    void DTimer::timeIn(QString Time)
    {
    qDebug()<<"Pobrano czas timera:"<<Time;
    iTime=Time.toInt()*1000;
    timer=new QTimer(this);
    if(iTime>0){
    timer->start(iTime);

    connect(timer, SIGNAL(timeout()),
            this, SLOT(timerOut()));
    }
    

    }

    void DTimer::timerOut()
    {
    qDebug()<<"Timer shoots";
    }

    Main cpp:

    ObtainmentData ObtainTime;
    DTimer dTimer;

           engine.rootContext()->setContextProperty("obtainTime", &ObtainTime);
    
           QObject::connect(&ObtainTime, SIGNAL(sendData(QString)),
                            &dTimer, SLOT(timeIn(QString)));
    

    qml

    TextField{id:timeSet
    anchors.centerIn: zadanyCzas
    width: 40
    height: 20

                  onTextChanged: obtainTime.getData(timeSet.text);
                 }
    

    This is the whole code for the QTimer


  • Lifetime Qt Champion

    Hi
    I would move
    timer=new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timerOut()));
    to constructor of DTimer


  • Lifetime Qt Champion

    @DdsS you already have a member *timer, but don't use it. Create this timer in the constructor as @SGaist said. remove the new QTimer line from the slot timeIn. It should work.

    Edit: @mrjj is right. Multiple connects will lead to such phenomena. The slot is called from multiple timers!



  • Thank you Guys for your reply. It works. I was struggle with it for a couple days your answers are very valuable . How ever I Did not find anything about moving it to constructor in documentation (maybe it was my lack of knowledge).


  • Lifetime Qt Champion

    @DdsS
    Hi
    Well, the doc wont mention it as it applies to all dynamic object creation. ( not just a timer)
    If you want to only create one instance (of any class) , you should only new it once and hence the constructor
    is good place.
    The reason to move the connect is Qt support connecting multiple times, even to same objects so
    often you only run the connect statement once as not to get more than one connection.

    So often you want to keep any connect statement near where you create the object.



  • Thank You very much for Your advise. I'll remeber it. This is very helpful.


Log in to reply