Есть ли альтернативное решение для вызова лямбда-функции 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: «Выполните следующее, но обработайте все остальное раньше»?


person Tobias Leupold    schedule 12.08.2018    source источник
comment
я знаю, что это единственный способ, но я мог бы использовать более читаемый способ: QTimer::singleShot(0, this, &QLineEdit::selectAll);   -  person eyllanesc    schedule 12.08.2018
comment
Нам на самом деле лямбда здесь не нужна, спасибо за подсказку :-)   -  person Tobias Leupold    schedule 12.08.2018
comment
Я думаю, вам это нужно, но вы этого не хотите. ;)   -  person eyllanesc    schedule 12.08.2018
comment
Мне не нужен QTimer…   -  person Tobias Leupold    schedule 12.08.2018
comment
Почему вы этого не хотите? Вы создаете какие-либо проблемы?   -  person eyllanesc    schedule 12.08.2018
comment
Мне просто интересно, есть ли другой способ   -  person Tobias Leupold    schedule 12.08.2018


Ответы (2)


Вы можете сделать это:

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

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

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

person Peter Ha    schedule 13.08.2018
comment
Спасибо за информацию! Речь шла только о том, является ли это одним из возможных способов или путем. Но, по-видимому, на данный момент Qt не предоставляет другого метода. Ну ведь с методом QTimer::singleShot работает. - person Tobias Leupold; 13.08.2018

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

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

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

работать нормально!

person Saber    schedule 13.08.2018
comment
Спасибо за информацию! Но вопрос был не об этом конкретном случае с проблемой выбора в фокусе, а об общем пути для такого случая. - person Tobias Leupold; 13.08.2018