2016-06-09 12 views
0

Я использовал эту функцию в моей программе:Объяснения о функции задержки QStateMachine

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); 
} 

Я сделал копию пасту из примера, и я не понимаю эту часть кода:

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

Anyone может объяснить мне, что это за код? Как это работает в программе?

PS. Я пытался изменить этот код с этим, но это не сработало:

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); 

ответ

3

Есть два QTimer::start slots, один без параметров и один с int msec параметром. Чтобы подключиться к правильному с новым синтаксисом подключения, вы должны указать тип слота с помощью static_cast.

Таким образом, в этой строке:

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

Вы подключаетесь к QTimer::start слот, который не принимает никаких аргументов.

Если у вас есть сигнал с int параметром и вы хотите подключиться к QTimer::start(int msec) слоту, вы могли бы сделать это следующим образом:

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

Вы можете прочитать больше об использовании перегруженных сигналов/слотов с новым connect синтаксис here.

Вы можете также использовать qOverload, чтобы удалить ненужный код static_cast.

В фрагменте, в котором вы используете выражения лямбда, вы фиксируете timer по ссылке. Вы должны захватить его значение вместо:

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

+1, что интересно ... в этом случае вы думаете, что лучше использовать старую систему для ясности/простоты использования: 'подключения (State1, СИГНАЛ (ввод (int)), таймер, SLOT (start (int))); '? –

+0

@code_fodder Это то, что я обычно делаю. Старый синтаксис гораздо легче читать и писать при работе с перегруженными сигналами/слотами. – thuga

+0

@thuga, возможно, но я считаю, что стоит заплатить цену более сложного синтаксиса, в интересах проверки времени компиляции. Обратите внимание, однако, что в Qt 5.7 мы можем получить лучшее из обоих миров, где вспомогательные функции были добавлены для абстрагирования сложного синтаксиса. Напр. QOverload :: of (& QTimer: start) – ManuelH