Search code examples
qtparameterssignals

emit signal with delay


the goal that I want to achieve is to emit a signal but delay it some time before it is actually emitted.

My idea for this was something like this:

emitLater(QObject *obj, QEvent *event, int msDelay)
{
    QTimer...
    connect(timout to obj and event...
    start timer with msDelay...

    //maybe I might need a public timer of some sort but the idea is clear
}

So this approach failed with the QEvent parameter because Signals could not be converted to QEvents.

I tried calling with std::bind in a couple of variations but I couldn't get it to work:

//the call
std::function<void(void)> signal = std::bind(&CustomPushButton_Header::clicked, &uiWindow->btnHeader_left); //just a random button to connect a valid signal
emitLater(signal, 2000);

//the function
emitLater(std::function<void(void)>, int msDelay)
{
    qDebug() << "hi";
}

I would appreciate a solution that works for all Objects and all Signals... maybe only the part which does call the function. I think the delay will turn out easy.

Or you have a different and even easier approach. That would be nice.

some sources I looked in:


Solution

  • There is a function QTimer::singleShot() that can trigger a signal/slot after a certain amount of time. I implemented it like this:

    void MyWindow::emitLater(const QObject *obj, const char *signalOrSlot, int msDelay)
    {
        //use QTimer::singleShot() to trigger the signal/slot after a certain amount of time
        QTimer::singleShot(msDelay, obj, signalOrSlot);
    }
    

    and use it like this:

    void MyWindow::on_pushButton_5_clicked()
    {
        //trigger the "doing fancy stuff" function after 5 seconds (= 5000 ms)
        emitLater(this, SLOT(setText()), 5000);
    }
    
    void MyWindow::setText()
    {
        //do some fancy stuff
        ui->label_3->setText("Hello World!");
    }
    

    An alternative would be in the answer from ΦXocę 웃 Пepeúpa ツ and uses a lambda expression as call function for the QTimer::timout() signal:

    void MyWindow::on_pushButton_5_clicked()
    {
        //initialize timer
        QTimer* t= new QTimer(this);
        t->setSingleShot(true);
    
        //do some fancy stuff after timeout
        connect(t, &QTimer::timeout, [this]()
        {
            ui->label_3->setText("Hello World!");
        });
    
        //start the timer with delay of 5 seconds (= 5000 ms)
        t->start(5000);
    }