Есть ли альтернативное решение для вызова лямбда-функции QTimer::singleshot(0)

Я только что реализовал QLineEdit это выбирает текст сразу после получения фокуса. Я создал производный класс и добавил

virtual void focusInEvent(QFocusEvent *event) override;

в шапку. Сначала я попытался реализовать это так:

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

но он не выделил бы текст, так как, по-видимому, некоторые вещи еще не были обработаны selectAll() называется.

Рабочим решением является поставить selectAll() позвонить в QTimer::singleShot лямбда звонить с 0 секунд ожидания вот так:

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

Это позволяет все обрабатывать раньше selectAll() вызывается и все работает нормально.

Это только один пример, я уже сталкивался с этой проблемой несколько раз. Так что мне интересно, есть ли предопределенный способ сказать Qt "Выполнить следующее, но обработать все остальное раньше"?

2 ответа

Решение

Вы могли бы сделать это:

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

Это спорно, является ли это лучше, хотя; также это работает только для слотов и других invokables, объявленных с Q_INVOKABLE и не для всех методов.

Стилистически я согласен с вами, что было бы неплохо иметь API для этого; QTimer::singleShot() конструкция выглядит немного странно (но работает отлично).

В определении класса добавьте код: signals: void focusIn();

в функции конструктора добавьте код: connect(this, &MyLineEdit::focusIn, this, &QLineEdit::selectAll, Qt::QueuedConnection);

в функцию focusInEvent добавьте код: emit this->focusIn();

работать отлично!

Другие вопросы по тегам