JavaFX 8: как добавить временную задержку к слушателю?

Сейчас я работаю над приложением JavaFX 8, где у меня есть tableView и некоторые текстовые поля выше, которые позволяют искать/фильтровать определенные столбцы в tableView. Я добавил прослушиватель к textFields, чтобы автоматически запускать фильтрацию при обнаружении изменения. Я использовал код ниже, чтобы сделать это.

textField_filterAddress.textProperty().addListener((observable, oldValue, newValue) -> {
            doSomething(); // in this case, filter table data and refresh tableView afterwards
        });

Теперь мой вопрос: какой самый простой способ интегрировать какую-то временную задержку, прежде чем фильтрация сработает? Я хотел бы подождать несколько миллисекунд, потому что каждый раз, когда пользователь фильтрует, он выполняет новый запрос к базе данных, и я не думаю, что это необходимо для каждого символа, который вводит пользователь. Я лучше подожду, пока он/она закончил свой ввод. Есть ли какая-то функция, подобная этой, уже встроенная во весь слушатель? Или мне нужно реализовать собственное решение? Если да, то как? Я подумал о каком-то решении для параллелизма, чтобы остальная часть программного обеспечения не зависала в течение периода ожидания. Но я подумал, что спрошу здесь, есть ли более простое решение, прежде чем слишком много думать о своем собственном пути...

Заранее большое спасибо!


person benkenobi26    schedule 14.01.2016    source источник
comment
Сколько всего данных вы ожидаете? Если это не слишком много, может быть разумно сначала загрузить все и использовать FilteredList.   -  person Itai    schedule 14.01.2016
comment
sillyfly, к сожалению, изначально мне не разрешили загрузить все, потому что это был университетский проект с определенными ограничениями   -  person benkenobi26    schedule 03.02.2016


Ответы (2)


Приведенный ниже код запланирует что-то сделать после задержки в 1 секунду с момента последнего изменения текстового поля. Если текстовое поле изменяется в течение этого 1-секундного окна, предыдущее изменение игнорируется, и что-то планируется выполнить с новым значением через 1 секунду от самого последнего изменения.

PauseTransition pause = new PauseTransition(Duration.seconds(1));
textField.textProperty().addListener(
    (observable, oldValue, newValue) -> {
        pause.setOnFinished(event -> doSomething(newValue));
        pause.playFromStart();
    }
);

Я не проверял это, но это должно работать :-)

Более сложным решением может быть использование «забывающего» приостанавливаемого потока событий ReactFX. Решения на основе ReactFX обсуждаются в соответствующем вопросе:

person jewelsea    schedule 14.01.2016
comment
привет, драгоценности, мой ответ также задерживается: D В итоге я использовал ваше решение, если оно сработало отлично, спасибо за это! - person benkenobi26; 03.02.2016

Интересная проблема, и я уверен, что другие имели дело с. Я обдумываю это впервые и не знаю, насколько практично это предложение, но вот:

Попросите слушателей вашего текстового поля отправить уведомление в очередь. Затем используйте метод util.TimerTask, который выполняется с выбранным вами интервалом времени для обработки очереди, и используйте его для создания нового фильтра (или нет).

Время ожидания в приведенном выше примере может варьироваться, поэтому, чтобы сделать его более последовательным, отправьте идентификатор текстового поля с отметкой времени и запустите таймер чаще, а новый фильтр обрабатывайте только по истечении определенного времени. .

Существуют различные параллельные очереди, которые можно использовать для хранения данных.

person Phil Freihofner    schedule 14.01.2016