2

Problem: I have a function void myFunc(data)

I am reading data from database using QSqlQuery:

QSqlQuery qry;
if (qry.exec("SELECT data, interval from table"))
{
   while(qry.next())
   {
       // Somehow create and call function: myFunc(int data) periodically with interval = interval
   }
}

As far as I understand I could use a timer like that:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(myFunc()));
timer->start(interval); //time specified in ms

but how can I pass argument data to myFunc when I create this timer?

John Davis
  • 172
  • 1
  • 19

4 Answers4

6

If you use C++11, you can connect your timer to a lambda function in which you capture your data value.

Example (untested):

int interval = 500;
int data = 42;

QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [data] {
    /* Implement your logic here */
});
epsilon
  • 2,849
  • 16
  • 23
2

One more option: have a QObject-derived class that runs the function calling QObject::startTimer. In this same class, use a QMap<int, int> where each pair has the timer id as key and the data as value.

A simple implementation:

#include <QObject>
#include <QMap>

class TimedExecution : QObject
{
    Q_OBJECT
public:
    TimedExecution() : QObject(0){}
    void addFunction(int data, int interval);
protected:
    void timerEvent(QTimerEvent *event);
private:
    QMap<int, int> map;
};

Use the addFunction method to create a new timed execution task (the passed interval is assumed to be expressed in seconds, here):

void TimedExecution::addFunction(int data, int interval)
{
    map.insert(startTimer(interval * 1000), data);
}

Start the same function in the overridden timerEvent method, passing the data retrieved from the map, using the timer id retrieved from the timer event as the map key:

void TimedExecution::timerEvent(QTimerEvent *event)
{
    myFunc( map[event->timerId()] );
}
p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35
2

If you can use Qt5 and C++11 then you can leverage std::bind:

for example, assuming decltype(this)==MyClass*:

connect(timer, &QTimer::timeout, this, std::bind(&MyClass::myFunc,this,data));
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
IlBeldus
  • 1,040
  • 6
  • 14
1

You have lots of options:

  • As mentioned in comments store the int data in this, maybe in a std::map<QTimer*, int> so that when you have multiple timers you can lookup the correct value and call myFunc with it. Since you have not stated if myFunc is one function or there can be multiple, you may have to store the function as well
  • You can make a class which gets the data value in the constructor, saves it in a member, you connect a slot of that class to the timer, and from the slot invoke myFunc() with the stored value
  • You can make a class that inherits from QTimer and has the data you need, use that class when creating the timer instead of the plain QTimer, and then in the slot myFunc you can access that instance via QObject::sender(), cast it to your type and do whatever needs to be done.
Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71