I'm working on an JavaFX 8 app right now, where i have a tableView and some textFields above which make it possible to search/filter for certain columns in the tableView. I have added a listener to the textFields, to trigger the filtering automatically when a change is detected. I used the code below to do this.
textField_filterAddress.textProperty().addListener((observable, oldValue, newValue) -> {
doSomething(); // in this case, filter table data and refresh tableView afterwards
});
My question now is:
what's the easiest way to integrate some kind of time delay, before the filtering gets triggered? I'd like to wait a few milliseconds, because everytime the user is filtering it's executing a new database query and i don't think this is necessary for every single char that the user puts in. I'd rather wait until he/she finished his input.
Is there some kind of feature like this already built into the whole listener thing? Or do i have to implement my own solution? If so, how? I thought about some kind of concurrency solution, so the rest of the software won't freeze during the waiting period. But i thought i'd ask here if there is an easier solution before thinking too much about my own way...
Big thanks in advance!
The code below will schedule to do something after a 1 second delay from the last time a text field changes. If the text field changes within that 1 second window, the previous change is ignored and the something is scheduled to be done with the new value 1 second from the most recent change.
PauseTransition pause = new PauseTransition(Duration.seconds(1));
textField.textProperty().addListener(
(observable, oldValue, newValue) -> {
pause.setOnFinished(event -> doSomething(newValue));
pause.playFromStart();
}
);
I didn't test this, but it should work :-)
A more sophisticated solution might be to make use of a "forgetful" ReactFX suspendable event stream. ReactFX based solutions are discussed in the related question:
- Wait before Reacting to a Property Change JavaFX 8
Interesting problem, and one which I'm sure others have dealt with. I'm thinking this through for the first time and don't know how practical this suggestion is, but here goes:
Have your text field listeners send a notification to a queue. Then, use a util.TimerTask method that executes at your preferred time interval to process the queue, and use that to build a new filter (or not).
The wait time in the above could be rather varied, so to make it a bit more consistent, send the text field ID with a time stamp and have the Timer run more frequently and only process the new filter if a certain amount of time has elapsed.
There are various concurrency-safe queues that could be used to house the data.