2013-08-14 1 views
12

я в настоящее время есть метод, который является следующимкак добавить вторую задержку 1 с помощью QTimer

void SomeMethod(int a) 
{ 

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

    //After one sec 
    SomeOtherFunction(a); 
} 

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

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

+0

Ожидаете ли вы обрабатывать сигналы чаще, чем период задержки? – Linville

+0

@Linville Да Моя задержка будет на одну секунду, и сигналы могут вызываться несколько раз за секунду – Rajeshwar

ответ

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's 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. Он включен здесь, чтобы попытаться сохранить примерный код рядом с вопросом.

+0

Я вижу, что вы используете переменную-член класса и сохраняете параметр. Однако это будет многопоточным. Так будет ли это безопасно? – Rajeshwar

+0

Я бы просто предостерег от этого решения, что если SomeMethod (..) вызывается быстрее, чем раз в секунду, значение m_a будет раздавлено до того, как оно будет использовано. – Linville

+0

Это может быть, в зависимости от того, как вы его используете. Если вы устанавливаете и получаете переменную-член в разных потоках, то убедитесь, что вы используете QMutex для ее блокировки перед настройкой/получением. Если вы передаете значение между потоками, то выполнение этого через механизм слота сигнала гарантирует, что он будет потокобезопасным. – TheDarkKnight

1

Если вы звоните 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 
} 
43

На самом деле, есть гораздо более элегантное решение на ваш вопрос, который не требует переменных-членов или очереди. С Qt 5.4 и C++ 11 вы можете run a Lambda expression right from the QTimer::singleShot(..) method! Если вы используете Qt 5.0 - 5.3, вы можете использовать метод подключения до connect the QTimer's timeout signal to a Lambda expression, который вызовет метод, который необходимо отложить с помощью соответствующего параметра.

Редактировать: С выпуском 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); 
} 
+0

Это очень приятно. Слишком плохо, вы не можете использовать лямбда-выражение со статическим 'QTimer :: singleShot()'. –

+0

@Roku, согласился! Это [QTBUG-26406] (https://bugreports.qt-project.org/browse/QTBUG-26406). Надеюсь, они обратятся к нему в ближайшее время! – Linville

+0

Также я не использую C++ 11 – Rajeshwar

0

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

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

Смежные вопросы