无需文本框内部获取条码扫描器输入

12
我有一个条形码扫描仪,在我的Java应用程序中,当使用条形码扫描产品时,我需要弹出一个窗口来显示与条形码相关联的所有信息,这些信息来自数据库。应用程序中没有文本框,我需要在内部处理这一部分。我该如何做?有什么建议吗?我正在使用Swing进行UI设计。
编辑:
条形码扫描仪是USB型号。如果我们扫描了一些东西,它会将结果输出到具有焦点的文本框中。但我没有在打开的页面上使用文本框。我能否使用某个隐藏的文本框来读取值呢?

我不确定你在问什么(踩票不是我)。 - Moonbeam
需要更多的细节。条形码扫描器是您的应用程序的一部分还是第三方独立应用程序?您需要文本框字段来做什么?条形码扫描器如何/应该/可以与您的应用程序通信? - bezmax
但是当扫描完成后,我该如何触发像弹出窗口之类的事件?换句话说,应用程序在扫描完成之前什么都不知道。那么如何处理这个问题? - Deepak
@Deepak 所以应用程序不知道何时等待扫描?在这种情况下,它可以在测量它们之间的时间时接受任何数字按键 - 条形码扫描仪通常以相同速率快速发送按键。这将使应用程序大致区分用户的(意外)按键和扫描仪的按键。这是简单的方法。或者,如果扫描仪有一些SDK或您想为其编写驱动程序,则可以直接进行通信(这是困难的方法)。 - pingw33n
@Deepak 应用程序必须以某种方式识别扫描仪输入的按键序列。因为按键可以由用户使用常规键盘触发,所以我建议区分扫描仪输入和用户输入的方法。扫描仪快速发送按键,并以相同的速率发送(我猜),因此,如果应用程序接收到足够快且稳定速率的按键,它几乎可以确定它们来自扫描仪。 - pingw33n
显示剩余8条评论
3个回答

9

由于条形码扫描器只是在读取每个条形码后发送按键代码和ENTER的设备,因此我会使用键盘监听器。

final Frame frame = new Frame();
frame.setVisible(true);

frame.addKeyListener(new KeyAdapter() {

    @Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ENTER) {
            // your code is scanned and you can access it using frame.getBarCode()
            // now clean the bar code so the next one can be read
            frame.setBarCode(new String());
        } else {
            // some character has been read, append it to your "barcode cache"
            frame.setBarCode(frame.getBarCode() + e.getKeyChar());
        }
    }

});

3
这个问题在于用户可以通过键盘按下一些键,然后按回车键,应用程序会将其视为捕获的条形码。此外,并不是所有的条形码读取器都发送ENTER后缀字符。 - Jaime Hablutzel

7

由于无法通过frame.addKeyListener获得输入,我使用了这个实用程序类,它使用KeyboardFocusManager:

public class BarcodeReader {

private static final long THRESHOLD = 100;
private static final int MIN_BARCODE_LENGTH = 8;

public interface BarcodeListener {

    void onBarcodeRead(String barcode);
}

private final StringBuffer barcode = new StringBuffer();
private final List<BarcodeListener> listeners = new CopyOnWriteArrayList<BarcodeListener>();
private long lastEventTimeStamp = 0L;

public BarcodeReader() {

    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() != KeyEvent.KEY_RELEASED) {
                return false;
            }

            if (e.getWhen() - lastEventTimeStamp > THRESHOLD) {
                barcode.delete(0, barcode.length());
            }

            lastEventTimeStamp = e.getWhen();

            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                if (barcode.length() >= MIN_BARCODE_LENGTH) {
                    fireBarcode(barcode.toString());
                }
                barcode.delete(0, barcode.length());
            } else {
                barcode.append(e.getKeyChar());
            }
            return false;
        }
    });

}

protected void fireBarcode(String barcode) {
    for (BarcodeListener listener : listeners) {
        listener.onBarcodeRead(barcode);
    }
}

public void addBarcodeListener(BarcodeListener listener) {
    listeners.add(listener);
}

public void removeBarcodeListener(BarcodeListener listener) {
    listeners.remove(listener);
}

}

1
非常好的解决方案,但有些条形码阅读器默认不发送ENTER键后缀,在您的代码中我看不到任何捕获条形码的方法,如果没有发送ENTER键,则无法捕获条形码。 - Jaime Hablutzel

1
在某种程度上,类似于@Cyrusmith的解决方案,我创建了一个“概念验证”解决方案(目前有一些限制,但您可以修复它们:)),试图解决此帖子中先前解决方案的限制:
  • 它支持不发送条形码字符串结尾的ENTER键的条形码阅读器。
  • 如果焦点当前在swing文本组件上,并且捕获到条形码,则条形码不会传递给文本组件,而只会传递给条形码侦听器。

参见 https://stackoverflow.com/a/22084579/320594


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接