Tobias Leupold
Tobias Leupold

Reputation: 1722

Is there an alternative solution for a QTimer::singleshot(0) lambda function call

I just implemented a QLineEdit that selects it's text right after getting focus. I created a derived class and added

virtual void focusInEvent(QFocusEvent *event) override;

to the header. I first tried to implement it like so:

void MyLineEdit::focusInEvent(QFocusEvent *event)
{
    QLineEdit::focusInEvent(event);
    selectAll();
}

but it wouldn't select the text, as apparently, some stuff wasn't processed yet at the time selectAll() is called.

The working solution is to put the selectAll() call in a QTimer::singleShot lambda call with 0 seconds to wait like so:

void MyLineEdit::focusInEvent(QFocusEvent *event)
{
    QLineEdit::focusInEvent(event);
    QTimer::singleShot(0, [this]() { selectAll(); } );
}

This lets everything be processed before selectAll() is invoked and everything works fine.

This is only one example, I already ran into this problem several times. So I wonder if there's a pre-defined method of telling Qt "Execute the following, but process everything else before"?

Upvotes: 0

Views: 830

Answers (3)

David Faure
David Faure

Reputation: 1997

Since Qt 5.10 (this commit) you can do QMetaObject::invokeMethod(this, &QLineEdit::selectAll, Qt::QueuedConnection);

I think it's better than a 0s single-shot timer because you don't have to register a temporary timer, invokeMethod just posts an event.

Upvotes: 1

Saber
Saber

Reputation: 21

in the class define, add the code:

signals:
    void focusIn();

in the constructor function, add the code:

connect(this, &MyLineEdit::focusIn, this, &QLineEdit::selectAll, Qt::QueuedConnection);

in the focusInEvent function, add the code:

emit this->focusIn();

work fine!

Upvotes: 1

Peter Ha
Peter Ha

Reputation: 306

You could do this:

QMetaObject::invokeMethod(this, "selectAll", Qt::QueuedConnection);

It is debatable whether this is nicer though; also it only works for slots and other invokables declared with Q_INVOKABLE and not for all methods.

Stylistically I agree with you that it would be nice to have an API for this; the QTimer::singleShot() construct looks a bit strange (but works fine).

Upvotes: 0

Related Questions