[英]How can read input from barcode scanner with JavaFX
我有条形码扫描仪,我可以在我专注于文本字段时读取输入,而不像键盘那样有任何问题。
我的问题如何我可以读取条形码输入如果我没有专注于文本字段,换句话说如何让事件监听器听取条形码扫描器。
它应该类似于此处提供的Java Swing解决方案。
我假设来自条形码扫描仪的最终字符是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没有设置KeyCode ,因此您无法执行此操作 :
if (event.getCode().equals(KeyCode.ENTER)) {
//...
}
我已根据@ 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年前发布的,但我仍然将解决方案留在那里,也许这对将来的某人有帮助=)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.