简体   繁体   English

如何使用JavaFX从条形码扫描仪读取输入

[英]How can read input from barcode scanner with JavaFX

I have Barcode Scanner i can read the input in the when i focus on the text field without any problem just like keyboard. 我有条形码扫描仪,我可以在我专注于文本字段时读取输入,而不像键盘那样有任何问题。

My question how i can read the barcode input if i do no focus on the textfield in other word how make event listener to listen to the Barcode Scanner. 我的问题如何我可以读取条形码输入如果我没有专注于文本字段,换句话说如何让事件监听器听取条形码扫描器。

It should work analog to the Java Swing solution presented here . 它应该类似于此处提供的Java Swing解决方案。

I assume the final character coming from the barcode scanner is ENTER. 我假设来自条形码扫描仪的最终字符是ENTER。 If not, you must check how to know when the barcode is done, eg by the expected length or by testing for summed up time between the key events or whatever. 如果没有,您必须检查如何知道条形码何时完成,例如通过预期长度或通过测试关键事件之间的总计时间等。

The KeyEvents from your barcode scanner should come fast, so the time between two events should be rather short. 条形码扫描器的KeyEvents应该很快,因此两个事件之间的时间应该相当短。 To filter out manual typing, the StringBuffer is reset if events come too slow. 要过滤掉手动输入,如果事件太慢,则会重置StringBuffer。

In your KeyListener , you can now implement this method: 在KeyListener中 ,您现在可以实现此方法:

private final StringBuffer barcode = new StringBuffer();
private long lastEventTimeStamp = 0L;

// ...

public void keyTyped(KeyEvent keyEvent) {
    long now = Instant.now().toEpochMilli();

    // events must come fast enough to separate from manual input
    if (now - this.lastEventTimeStamp > this.threshold) {
        barcode.delete(0, barcode.length());
    }
    this.lastEventTimeStamp = now;

    // ENTER comes as 0x000d
    if (keyEvent.getCharacter().charAt(0) == (char) 0x000d) {
        if (barcode.length() >= this.minBarcodeLength) {
            System.out.println("barcode: " + barcode);
        }
        barcode.delete(0, barcode.length());
    } else {
        barcode.append(keyEvent.getCharacter());
    }
    keyEvent.consume();
}

This is just a rough implementation which probably requires some fine tuning, but I've tested it in an FXML controller for a GridPane and for the barcode scanner I have it works. 这只是一个粗略的实现,可能需要一些微调,但我已经在一个用于GridPane的FXML控制器中测试它,而对于条形码扫描器,我有它的工作原理。

Note: The KeyEvent.KEY_TYPED does not have the KeyCode set , so you cannot do this : 注意: KeyEvent.KEY_TYPED没有设置KeyCode ,因此您无法执行此操作

if (event.getCode().equals(KeyCode.ENTER)) {
//...
}

I've wrote better solution based on @l00tr answer 我已根据@ l00tr回答编写了更好的解决方案

public final class BarcodeAccumulator {

    public interface OnBarcodeListener {

        void onBarcodeScanned(String barcode);
    }

    private static final char BACKSPACE = '\b';
    private static final char CONTROL_V = 0x0016;
    private static final char CONTROL_Z = 0x001A;
    private static final char CARRIAGE_RETURN = 0x000d;

    private final StringBuffer buffer = new StringBuffer();

    private OnBarcodeListener barcodeListener;

    public void setBarcodeListener(OnBarcodeListener barcodeListener) {
        this.barcodeListener = barcodeListener;
    }

    public void accumulate(final TextField textField) {
        if (Objects.nonNull(textField)) {
            textField.setOnKeyTyped(event -> {
                for (char character : event.getCharacter().toCharArray()) {
                    if (Character.isISOControl(character)) {
                        if (textField.isFocused()) {
                            if (character == BACKSPACE) {
                                if (buffer.length() > textField.getCaretPosition()) {
                                    remove(textField.getCaretPosition());
                                }
                                break;
                            }
                            if (character == CONTROL_V) {
                                add(textField.getText());
                                break;
                            }
                            if (character == CONTROL_Z) {
                                clear();
                                add(textField.getText());
                                break;
                            }
                            if (character == CARRIAGE_RETURN) {
                                notifyListener(buffer.toString());
                                clear();
                                break;
                            }
                        }
                        continue;
                    }
                    add(String.valueOf(character));
                }
            });
        }
    }

    public void add(String character) {
        buffer.append(character);
    }

    public void remove(int position) {
        buffer.deleteCharAt(position);
    }

    public void clear() {
        buffer.delete(0, buffer.length());
    }

    private void notifyListener(String barcode) {
        if (Objects.nonNull(barcodeListener)) barcodeListener.onBarcodeScanned(barcode);
    }

You must to handle all control characters such as ctrl+v etc., 'cause sometimes users can paste value inside text field manually or from buffer with shortcuts. 您必须处理所有控制字符,例如ctrl + v等,因为有时用户可以手动或在带有快捷方式的缓冲区中将值粘贴到文本字段中。 Besides, this solution follows for caret position and listen "backspace" event, and in case, when user removes any character from text field, this action also change buffer value. 此外,此解决方案遵循插入符号位置并侦听“退格”事件,如果用户从文本字段中删除任何字符,此操作也会更改缓冲区值。 I see that the question and answer were posted 3 years ago, but I still leave my solution there, maybe it will be help for somebody in future =) 我看到问题和答案是3年前发布的,但我仍然将解决方案留在那里,也许这对将来的某人有帮助=)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM