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.<
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
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.
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.
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();
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);
}
});
}
}