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

时间:2015-07-20 09:48:25

标签: java javafx

我有条形码扫描仪我可以在我专注于文本字段时读取输入而没有任何问题,就像键盘一样。

我的问题如何在没有关注文本字段的情况下如何阅读条形码输入,换句话说如何让事件监听器听取条形码扫描器。

2 个答案:

答案 0 :(得分:3)

它应该类似于Java Swing解决方案presented here

我假设来自条形码扫描仪的最终字符是ENTER。如果没有,您必须检查如何知道条形码何时完成,例如通过预期的长度或通过测试关键事件或其他任何事件之间的总计时间。

条形码扫描仪的KeyEvents应该很快,因此两个事件之间的时间应该相当短。要过滤掉手动输入,如果事件太慢,则会重置StringBuffer。

在您的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();
}

这只是一个粗略的实现,可能需要进行一些微调,但是我已经在一个用于GridPane的FXML控制器中测试了它,而对于条形码扫描器我已经测试了它。

注意: KeyEvent.KEY_TYPED does not have the KeyCode set,所以你不能这样做

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

答案 1 :(得分:0)

我已经根据@ 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);
    }

您必须处理所有控制字符,例如ctrl + v等,因为有时用户可以手动在文本字段中粘贴值,也可以使用快捷方式从缓冲区粘贴值。此外,此解决方案针对插入符位置和侦听“退格”事件,并且在用户从文本字段中删除任何字符的情况下,此操作也会更改缓冲区值。我看到问题和答案是3年前发布的,但我仍然将解决方案留在那儿,也许将来会对某人有所帮助=)