I am developing a system that allows the user to scan barcodes. The barcode scanner effectively behaves like a keyboard, “typing” each digit of the barcode at super-human speeds. For the sake of this example, let’s say that most amount of time between successive “key strokes” is 10 milliseconds.
I began by implementing an EventHandler that listens for numeric KeyEvents on the application’s Window. When a KeyEvent arrives, the handler does not yet know if it was entered by a human or by a barcode scanner (it will know 10 milliseconds from now). Unfortunately, I must make a decision now or risk locking up JavaFX’s main thread, so I automatically call keyEvent.consume() to prevent it from being handled.
After 10 milliseconds have elapsed, a timer wakes up and decides whether or not the KeyEvent was part of a barcode. If it was, the KeyEvents are concatenated together and handled by the barcode processing logic. Otherwise, I want to let the application handle the KeyEvent normally.
How can I force the application to handle a KeyEvent after I have already called keyEvent.consume() on it?
Here is my take on how this might be done.
The solution works by filtering the key events for the app, cloning them and placing the cloned events in a queue, then consuming the original events in the filter. The cloned event queue is processed at a later time. Events from the barcode reader are not refired. Events that are not from the barcode reader are refired so that the system can process them. Data structures keep track of whether the events have been processed already or not, so that the system can know in the event filter whether it truly has to intercept and consume the events or let them pass through to the standard JavaFX event handlers.
Sample program output:
Because I use a Timeline everything in my code runs on the FXApplicationThread, so I don’t have to worry about concurrency in my implementation. In implementation with a real barcode reader and barcode event processor, you may need some added concurrency protection as possibly multiple threads will be involved. Also you might not need the Timeline used in my code to simulate the delayed processing of the barcode system.