Davide Ferrari
Davide Ferrari

Reputation: 75

Explanation about QStateMachine delay function

I used this function in my program:

void delay(QState * state1, int millisecond, QAbstractState * state2) 
{
   auto timer = new QTimer(state1);
   timer->setSingleShot(true);
   timer->setInterval(millisecond);

   QObject::connect(state1, &QState::entered, timer, static_cast<void (QTimer::*)()>(&QTimer::start));
   QObject::connect(state1, &QState::exited,  timer, &QTimer::stop);

   state1 -> addTransition(timer, SIGNAL(timeout()), state2);
}

I made a copy-paste from an example and I did not understand this part of code:

QObject::connect(state1,..., static_cast<void (QTimer::*)()>(&QTimer::start));

Anyone can explain to me what this code is ? How it works in the program ?

PS. I tried to change that code with this but it didn't work:

QTimer *timer = new QTimer(state1);
.
.  //same code as before
.
QObject::connect(stato1,&QState::entered,timer,[&] {timer->start();} );
QObject::connect(stato1,&QState::exited, timer,[&] {timer->stop(); } );

stato1 -> addTransition(timer,SIGNAL(timeout()),stato2);

Upvotes: 0

Views: 543

Answers (1)

thuga
thuga

Reputation: 12931

There are two QTimer::start slots, one without parameters and one with int msec parameter. To connect to the correct one with the new connect syntax, you must specify the slot type with a static_cast.

So in this line:

QObject::connect(state1, &QState::entered, timer, static_cast<void (QTimer::*)()>(&QTimer::start));

You connect to QTimer::start slot which takes no arguments.

If you had a signal with an int parameter and you wanted to connect to QTimer::start(int msec) slot, you'd do it like this:

connect(this, &MyClass::mySignal, timer, static_cast<void (QTimer::*)(int)>(&QTimer::start));

You can read more about using overloaded signals/slots with the new connect syntax here.

You can also use qOverload to remove the need of the ugly static_cast.

In the snippet where you use lambda expressions, you capture timer by reference. You should capture it by value instead:

QObject::connect(stato1, &QState::entered, timer, [=]{timer->start();});

Upvotes: 3

Related Questions