1

I want to have my application react to barcodes being scanned to trigger button presses. For example the user could scan the ((PRINT)) barcode to activate the print button.

The barcodes will just be treated as if the user had entered some text. I am not sure if the scanners will be set up to append an enter or a tab or nothing on the end, so I don't want to make an assumption on that basis.

The application is a Java/Swing application.

I have looked at keybindings/action maps and the like, but they seem to be focussed on key chords/single key entries. I need it to not trigger the binding until the whole string is entered.

The tricky bit is that this should work wherever the user is focussed in the screen. They will not normally enter ( characters, so some kind of trigger on that might work. I am not sure how to handle the rest of the string though.

Edit: Apologies if it wasn't clear in the question, but the barcode scanner isn't anything "special" to the application, it's just like another keyboard. So the user won't be typing in (print), but effectively that is what the barcode scanner will be doing, if that makes sense.

So there are only two ways to trigger the print: pressing the button, or "typing" the string (print). The tricky part is that the user can be focussed anywhere on the application. I am only worried about if the application has focus as a whole, not which field the user is focussed on. The particular screen in question has checkbuttons and left/right selectors on it, so the user isn't necessarily going to be typing in to a field.

Greg Reynolds
  • 9,736
  • 13
  • 49
  • 60
  • You need to grab the keyboard input even if your application doesn't have focus? (Sorry, I didn't understand that part well.) Maybe this would help: [java.awt.KeyListener](http://docs.oracle.com/javase/6/docs/api/java/awt/event/KeyListener.html) and [How to write a key listener](http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html). – Petr Aug 30 '12 at 14:31

4 Answers4

3

I had a problem just like yours, and created a project (currently proof of concept with some problems) to make barcode handling in swing easier.

It is based in the fact that the barcode readers emulate a keyboard but differently to humans they "type" with a constant timing. It will basically allow you to listen to "barcode read" events.

The project location: https://github.com/hablutzel1/swingbarcodelistener

Demo usage:

public class SimpleTest extends JFrame {
    public SimpleTest() throws HeadlessException {

        // start of listening for barcode events
        Toolkit.getDefaultToolkit().addAWTEventListener(new BarcodeAwareAWTEventListener(new BarcodeCapturedListener() {
            @Override
            public void barcodeCaptured(String barcode) {
                JOptionPane.showMessageDialog(SimpleTest.this, "barcode captured: " + barcode);
            }
        }), AWTEvent.KEY_EVENT_MASK);
        // end of listening for barcode events


        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(new JLabel("Capture barcode demo"));
        getContentPane().add(new JTextField(25));
    }

    public static void main(String[] args) {
        SimpleTest simpleTest = new SimpleTest();
        simpleTest.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        simpleTest.setVisible(true);
        simpleTest.pack();
    }
}

It has some problems now but as a starting point I think it is ok, if you have time to improve it it would be great.

Jaime Hablutzel
  • 6,117
  • 5
  • 40
  • 57
1

Correct me if I missunderstood, but it sounds like you have a barcode-scanner which will enter text into a field. But you want to be alerted when the text in the field equals something (so an action can take place) regardless of how it was entered (by barcode scanner or key press).

I'd recommend using a DocumentListener to alert you of changes to the text field - this should work with both of your requirements.

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

public class TempProject extends Box{

    public TempProject(){
        super(BoxLayout.Y_AXIS);
        final JTextArea ta = new JTextArea();
        ta.getDocument().addDocumentListener(new DocumentListener(){

            @Override
            public void changedUpdate(DocumentEvent arg0) {
                doSomething();
            }

            @Override
            public void insertUpdate(DocumentEvent arg0) {
                doSomething();
            }

            @Override
            public void removeUpdate(DocumentEvent arg0) {
                doSomething();
            }

            public void doSomething(){
                if(ta.getText().equalsIgnoreCase("print")){
                        System.out.println("Printing...");
                        //Need to clear text in a separate swing thread
                        SwingUtilities.invokeLater(new Runnable(){
                            @Override
                            public void run() {
                                ta.setText("");
                            }});
                }
            }

        });

        add(ta);
    }


    public static void main(String args[])
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                frame.setContentPane(new TempProject());
                frame.setPreferredSize(new Dimension(500, 400));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }   


}
Nick Rippe
  • 6,465
  • 14
  • 30
  • Assuming he's allowed to have a text field, this is a +1 – MadProgrammer Aug 30 '12 at 23:17
  • 1
    Unfortunately the user won't be editing text in a text field, they could be clicking checkboxes or combo boxes etc., so I can't really rely on this solution. Thanks anywyay. – Greg Reynolds Aug 31 '12 at 08:33
  • 1
    Couldn't you just make the text box always be selected. EG when they click a check box or combo box the cursor returns to the text box after?! Don't know your application so don't know if this will or not! – Ollie Sep 28 '12 at 13:29
1

I do not completely understand the question, and this is a bit too long to put in a comment. As far as I understood it, you have a Swing application and a bar-code scanner which has 3 different ways to trigger the same operation

  • User enters some text ("print") in the UI and this triggers the print action
  • The UI has a print button which can be pressed by the user and this triggers the print action
  • User can scan a "print" bar code and this triggers the print action

The part I do not understand is why the scanning of the bar code, which should trigger the print action, has anything to do with the UI-part where the user can input text.

I assume the scanning of the barcodes happens on another thread then the Event Dispatch Thread. Once you scanned a barcode and parsed it, you need to trigger the "print" action. You can do this directly without bothering going through the UI.

Robin
  • 36,233
  • 5
  • 47
  • 99
  • Think about some one in a store, rather then having to hit the "print" button, they can use predefined "barcode" cards to perform actions - you see this a lot with clerk sign in's. I'd imagin it's the same process ... +1 though – MadProgrammer Aug 30 '12 at 23:18
  • @MadProgrammer But why bother then to go from barcode->text->action, and not just barcode->action (where the action possibly has a UI indication about what it is doing/going to do) – Robin Aug 31 '12 at 06:04
  • I think that's what he wants to do...Barcode->action that is. I'd personally attach a listener to the `AWTEventQueue` personally, but then how would you tell the difference between someone typing "PRINT" and the barcode?? – MadProgrammer Aug 31 '12 at 06:08
  • @MadPrgrammer - it's almost exactly as you describe, this application is for a packing bench in a warehouse, so the user is going to want to scan barcodes whenever possible rather than messing around with the mouse. The suggestion about AWTEventQueue looks like a pointer in the right direction, as I don't actually care if the user typing in the string triggers the print. The barcode will have initial characters on it that the user won't encounter in "normal" barcodes, so there should be no collision. – Greg Reynolds Aug 31 '12 at 08:32
1

This is my approach. It's working. Just get the miliseconds for ensure doesn't read twice. Just add a Key Listener (implemented in the same JFrame).

  @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
        logger().info("keytyped" + e.getKeyChar() + " code "+e.getKeyCode());
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            logger().info("all keys " + keyspressed);
            return;
        }
        // will not last more than a second...
        if (keyspressed == null || System.currentTimeMillis() - currentTimeMillis > 1000) {
            keyspressed = e.getKeyChar()+"";
            currentTimeMillis = System.currentTimeMillis();
        } else {
            keyspressed = keyspressed + e.getKeyChar();
            currentTimeMillis = System.currentTimeMillis();
        }
    }

    private String keyspressed = null;
    private long currentTimeMillis = System.currentTimeMillis();
Alfonso Tienda
  • 3,442
  • 1
  • 19
  • 34