Как добавить 1-секундную задержку с использованием Qtimer

В настоящее время у меня есть метод, который выглядит следующим образом

void SomeMethod(int a)
{

     //Delay for one sec.
     timer->start(1000);

     //After one sec
     SomeOtherFunction(a);
}

Этот метод фактически является слотом, который привязан к сигналу. Я хотел бы добавить задержку в 1 секунду с помощью Qtimer. Однако я не уверен, как это сделать. Поскольку таймер запускает сигнал, когда его закончен, и сигнал должен быть привязан к другому методу, который не принимает никаких параметров. Любое предложение о том, как я мог бы выполнить эту задачу.?

Обновление: Сигнал будет вызываться несколько раз в секунду, а задержка будет на секунду. Моя проблема здесь заключается в передаче параметра в слот, прикрепленный к сигналу таймаута() таймера. Мой последний подход состоял в том, чтобы сохранить значение в переменной memeber класса, а затем использовать мьютекс, чтобы защитить его от изменения во время использования переменной. Однако я ищу более простые методы здесь.

Ответ 1

Я немного смущен тем, как вы формулируете свой вопрос, но если вы спрашиваете, как получить сигнал таймаута таймера() для вызова функции с параметром, тогда вы можете создать отдельный слот для получения тайм-аут, а затем вызовите нужную функцию. Что-то вроде этого: -

class MyClass : public QObject
{
    Q_OBJECT

public:
    MyClass(QObject* parent);

public slots:

    void TimerHandlerFunction();
    void SomeMethod(int a);

private:
    int m_a;
    QTimer m_timer;

};

Реализация: -

MyClass::MyClass(QObject* parent)
    :QObject(parent)
{
    // connect the timer timeout to our TimerHandlerFunction
    connect(&m_timer, SIGNAL(timout()), this, SLOT(TimerHandlerFunction()));
}

void MyClass::SomeMethod(int a)
{
    m_a = a; // store the value to pass later

    m_timer.setSingleShot(true); // if you only want it to fire once
    m_timer.start(1000);
}

void MyClass::TimerHandlerFunction()
{
     SomeOtherFunction(m_a);
}

Обратите внимание, что класс QObject действительно имеет таймер, который вы можете использовать, вызывая startTimer(), поэтому вам фактически не нужно использовать отдельный объект QTimer. Он включен здесь, чтобы попытаться сохранить примерный код рядом с вопросом.

Ответ 2

На самом деле в вашем вопросе гораздо больше элегантного решения, которое не требует переменных-членов или очередей. С Qt 5.4 и С++ 11 вы можете запустить выражение Lambda прямо из метода QTimer::singleShot(..)! Если вы используете Qt 5.0 - 5.3, вы можете использовать метод connect для подключить сигнал тайм-аута QTimer к выражению Lambda, который вызовет метод, который вам нужен для задержки с соответствующим параметром.

Изменить: С выпуском Qt 5.4 это всего лишь одна строка кода!

Qt 5.4 (и позже)

void MyClass::SomeMethod(int a) {
  QTimer::singleShot(1000, []() { SomeOtherFunction(a); } );
}

Qt 5.0 - 5.3

void MyClass::SomeMethod(int a) {
  QTimer *timer = new QTimer(this);
  timer->setSingleShot(true);

  connect(timer, &QTimer::timeout, [=]() {
    SomeOtherFunction(a);
    timer->deleteLater();
  } );

  timer->start(1000);
}

Ответ 3

Если вы вызываете SomeMethod несколько раз в секунду, а задержка всегда постоянна, вы можете поместить параметр a в QQueue и создайте один таймер для вызова SomeOtherFunction, который получает параметр из QQueue.

void SomeClass::SomeMethod(int a)
{
    queue.enqueue(a);
    QTimer::singleShot(1000, this, SLOT(SomeOtherFunction()));
}

void SomeClass::SomeOtherFunction()
{
    int a = queue.dequeue();
    // do something with a
}

Ответ 4

Это не работает, потому что QTimer::start не блокирует.

Вы должны запустить таймер с помощью QTimer::singleShot и подключить его к слоту, который будет запущен после истечения времени QTimer.