8

I am having a hard time wording this question even though I don't think its that complicated.

I want to do something simalar to QTimer::singleshot() but I want it to still only call the SLOT once even if QTimer::singleshot() is called multiple times before it fires.

AMIC MING
  • 6,306
  • 6
  • 46
  • 62
sm11963
  • 93
  • 1
  • 1
  • 6

4 Answers4

14

If you only want to call a slot once off a timer you could look at something like

QTimer::singleShot(500, this, SLOT(MySlot()));

Then your guaranteed it will only happen once.

To clarify, by calling the static version of this rather then calling it from a existing timer it will only happen once.

simotek
  • 737
  • 6
  • 10
6

This should work. 

class MyObject
{

// ...
    QTimer* mTimer;
}

MyObject::MyObject()
{
    mTimer = new QTimer(this);
    mTimer->setSingleShot(true);
    connect(mTimer, SIGNAL(timeout()), SLOT(doStuff()));
}

MyObject::startOrResetTimer()
{
   mTimer->start(1000);
}
pcworld
  • 136
  • 2
  • 9
Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • +1 The key here is that if `singleShot` is true, the timer will be activated only once when `start()` is called. – Arnold Spence Jan 11 '13 at 01:17
  • Question is if you want to restart the timer if it is already running. Here, if startOrResetTimer is called every 900ms, the timer will be restarted all the time and never timeout. – Frank Osterfeld Jan 11 '13 at 08:11
  • @FrankOsterfeld If you want that, add `if (!mTimer->isActive())` before `start()`. – Timmmm Jan 11 '13 at 10:32
  • Timmmm: Sure, just wanted to point out that one has to decide which behavior is wanted. – Frank Osterfeld Jan 11 '13 at 10:41
  • IMO unnecessarily more polluted than @simotek's answer – fabian789 Sep 16 '14 at 14:19
  • @fabian789: I don't believe simotek's answer actually does what the question wants. The documentation does not support his claim that calling `QTimer::singleShot(...)` twice will only trigger the slot once. – Timmmm Sep 17 '14 at 18:35
4

You can use singleShot() static member function with lambda for this purpose easily:

QTimer::singleShot(2000, [=](){
    qDebug()<<"do something after 2000 msec...";
});
S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59
-2

Quick-and-dirty: use a boolean in your class and set it to true in the slot; ignore subsequent calls until the boolean is reset.

JvO
  • 3,036
  • 2
  • 17
  • 32
  • That is resource intensive if say the timer will call the function after days not seconds. – Zaid Jul 31 '17 at 07:21
  • A single boolean is resource intensive?? – JvO Aug 02 '17 at 12:39
  • If I understand correctly, if the code gets called hundreds of times per second, a day waiting could be a lot of time spent checking a bool. That's what @Zaid meant I think. – Zimano Feb 09 '18 at 09:00
  • @zimano I think the overhead of the hundreds of calls is more to worry about. Anyway, we don't know anything about the rest of the code or even the reason for the single usage, so this is all speculation. – JvO Feb 11 '18 at 20:54