2

I found some good Q/A here on my problem but couldn't find the right one.

I have a barcode reader that reads barcode and sends scanned code as keyboard input. It is alright I can catch input easily

browser.addKeyListener(new KeyAdapter() {   
    @Override public void keyPressed(KeyEvent e) {
        if(e.keyCode >=48 && e.keyCode <=57) {
            System.out.println("number caught");
        } 
    }
});

But I will have more inputs in my application so I need to know if it is send by barcode reader or by keyboard. I think it can be achieved by adding some timer in code that verifies how long is some "sequence" reading.

I just can not figure it out, (I mean logic behind it), I am missing piece of logic.

  1. User is typing some info, (alpha numerical)
  2. user desides to use barcode reader to read barcode

I tried timer e.g if(System.currentTimeMillis() - lastPressProcessed ??? 500) { after keyListener is triggered but I think I am missing something.

sidenote: USB barcode reads code fast so keystrokes are emulated really fast est whole barcode is written in about 1 second + carry /r/n (also enter is pressed).

sidenote2: barcodes are going to be different in length so I can not read just some length in short time and decide wether it is user input or barcode input (max numbers read 13 + enter).

sidenote3: I have no input field for barcode I am trying to achieve running it on "background".

I am seeking logic/pseudocode suggestions on topic.

related topics that are really close to mine are here, and here

Thank you.

edit

After deep tought I found out the solution I'll keep this Q here just for another users that might find this usable.

solution --moved to answer + edited

Community
  • 1
  • 1
Kyslik
  • 8,217
  • 5
  • 54
  • 87
  • You can post your solution as an answer and select it if it solved your problem. However, I don't think your code does what you think it does. You say "whole barcode is written in about 1 second", but your code allows for 1 second to elapse between two keystrokes and still treats the input as scanner input! "I have no input field for barcode", do you have other input fields and you are trying to prevent scanned data from going into those fields? – Enrico Jul 01 '13 at 22:50
  • Whenever is /r/n passed to program loop is "closed" so barcode is read. I changed time to 200 ms, I was worried about system "lag". I think this code meets my needs I know its not perfect but in this matter it is I ll update my solution because I made some changes also. I know I can post answers but I have to wait 2 (1?) days to accept it. There is not going to be a Java input, but HTML one. The Java program is there just to read barcodes and send them to webpage. – Kyslik Jul 02 '13 at 06:43
  • Also I am not worried about mixing users manual input with barcodes. While in "editing" mode barcode scanner is going to be "turned off" (in software matter). Please make more suggestions if you feel its needed. – Kyslik Jul 02 '13 at 06:56
  • See http://stackoverflow.com/a/22084579/320594 for an alternative (although not ready for production) – Jaime Hablutzel May 15 '14 at 03:11

2 Answers2

1

This code coveres everything I wanted to achieve, it reads just numbers (actualy numbers that are under F keys, not numbers that are on numpad, I had problem with it because scanner is keyboard dependant so I made function signsToNumbers() that converts signs !@#$%^&*() to numbers 1234567890. I may change this function because every key on keyboard has its own unique identifier + modifier, it seems that scanner sends also SHIFT modifier to the application but that is not as problem as it seems I'll just match e.keyCode.

The code below works as:

  1. waits for number input otherwise does nothing
  2. if 1st number is inserted it is looping in if condition until either 200ms is reached or '\r\n` is received
  3. sends data to server via URL

code

@Override public void keyPressed(KeyEvent e) {
    if (timer == true && System.currentTimeMillis() - lastTimer < 200) {
      if(e.keyCode >=48 && e.keyCode <=57) { //number pressed
          lastTimer = System.currentTimeMillis();
          myString = myString + Character.toString(e.character);
        }
        if(e.keyCode == SWT.CR) {
          myString = signsToNumbers(myString);
          newUrl = browser.getUrl()+ "/newcode/" + myString;
          browser.setUrl(newUrl);
          text.setText(newUrl);
          System.out.println(myString);
          System.out.println("barcode read");
          myString = "";
          timer = false;
          lastTimer = 0;
        }
    }else{
        if(e.keyCode >=48 && e.keyCode <=57) {
          lastTimer = System.currentTimeMillis();
          timer = true;
          myString = Character.toString(e.character);
        }
        myString = "";
        lastTimer = 0;
    }        
  }
});
Kyslik
  • 8,217
  • 5
  • 54
  • 87
1

Here you can download my solution:

http://jhead.hu/resource/java/general/BarcodeReader.java

The following code sample shows you, how to use it. When a new barcode is identified, an ActionEvent is generated and you can get the barcode via the getActionCommand() method. If the panel is not active you can send the characters further to the focus manager.

The only problem is that my barcode scanner sends the characters too fast so the character bits are sometimes mixed. I've got no better solution yet.

public class PanelWithBarcodeReading extends javax.swing.JPanel implements ActionListener {

    private BarcodeReader barcodeReader = new BarcodeReader();

    public PanelWithBarcodeReading() {
        initComponents();
        barcodeReader.addActionListener(this);
        barcodeReader.setParent(this);
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(barcodeReader);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (SwingUtilities.getWindowAncestor(this).isActive()) {
            System.out.println("BARCODE='" + e.getActionCommand() + "'");
        } else {
            barcodeReader.dispatchLastBarcodeAsKeyEvents();
        }
    }

    ...
}
JHead
  • 356
  • 2
  • 12