问题
I currently have a method which is as follows
void SomeMethod(int a)
{
//Delay for one sec.
timer->start(1000);
//After one sec
SomeOtherFunction(a);
}
This method is actually a slot that is attached to a signal. I would like to add a delay of one sec using Qtimer.However I am not sure on how to accomplish this. Since the timer triggers a signal when its finished and the signal would need to be attached to another method that does not take in any parameters. Any suggestion on how I could accomplish this task.?
Update : The signal will be called multiple times in a second and the delay will be for a second. My issue here is passing a parameter to the slot attached to timeout() signal of a timer. My last approach would be to store the value in a memeber variable of a class and then use a mutex to protect it from being changed while the variable is being used .however I am looking for simpler methods here.
回答1:
I'm a bit confused by the way you phrase your question, but if you're asking how to get the timer's timeout() signal to call a function with a parameter, then you can create a separate slot to receive the timeout and then call the function you want. Something like this: -
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;
};
Implementation: -
MyClass::MyClass(QObject *parent) : QObject(parent)
{
// Connect the timer's timeout to our TimerHandlerFunction()
connect(&m_timer, SIGNAL(timeout()), 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);
}
Note that the QObject class actually has a timer that you can use by calling startTimer(), so you don't actually need to use a separate QTimer object here. It is included here to try to keep the example code close to the question.
回答2:
Actually, there is a much more elegant solution to your question that doesn't require member variables or queues. With Qt 5.4 and C++11 you can run a Lambda expression right from the QTimer::singleShot(..) method! If you are using Qt 5.0 - 5.3 you can use the connect method to connect the QTimer's timeout signal to a Lambda expression that will call the method that needs to be delayed with the appropriate parameter.
Edit: With the Qt 5.4 release it's just one line of code!
Qt 5.4 (and later)
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:
If you are calling SomeMethod
multiple times per second and the delay is always constant, you could put the parameter a
to a QQueue and create a single shot timer for calling SomeOtherFunction
, which gets the parameter from the 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:
That doesn't work because QTimer::start
is not blocking.
You should start the timer with QTimer::singleShot
and connect it to a slot which will get executed after the QTimer times out.
来源:https://stackoverflow.com/questions/18236480/how-to-add-a-1-second-delay-using-qtimer