Getting input from barcode scanner internally without textbox - java

I have a barcode scanner and in my java application I have to bring a popup to display all the information associated with the barcode from database when the product is scanned using barcode. I have no textbox on the application I have to handle this part internally. How do I do this ? any suggestion ? I am using swing for UI.
EDIT
Barcode scanner is USB one. If we scan something it will output the result into the textbox which has focus. But I have no textbox working on the page opened. Can i work with some hidden textbox and read the value there ?

Since barcode scanner is just a device which sends keycodes and ENTER after reading of each barcode, I'd use a key listener.
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());
}
}
});

Since was not able to get input via frame.addKeyListener I have used this utility class which uses 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);
}
}

In some way similar to #Cyrusmith solution I have created a 'proof of concept' solution (with several limitations right now, but you are invited to fix them :) ) trying to solve the limitations on the previous solutions in this post:
It support barcode readers that doesn't send the ENTER at the end of barcode string.
If the focus is currently on a swing text component and barcode is captured, the barcode doesn't get to the text component and only to the barcode listener.
See https://stackoverflow.com/a/22084579/320594

Related

Java: The escape key is always pressed after dispatchEvent() for WINDOW_CLOSING on a JFrame

I have a simple JFrame that asks a user for a confirmation to exit when they click X to close the window, this works fine. I also wanted the user to be presented with the same option if they also pressed the escape key (ESC), unfortunately it seems to be trapped in a state where the escape key seems to be constantly pressed when it is not. Where is the mistake and why?
public class Zz extends javax.swing.JFrame implements Events {
boolean exitAttempt = false;
java.awt.event.WindowEvent closeEvent;
//public Zz() {}
public static void main(java.lang.String[] args) {
Zz zz = new Zz();
zz.dostuff();
}
public void dostuff() {
setSize(800, 600);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(javax.swing.JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent we) {
exitAttempt = true;
}
});
closeEvent = new java.awt.event.WindowEvent(
this, java.awt.event.WindowEvent.WINDOW_CLOSING);
setVisible(true);
java.awt.Canvas canvas = new java.awt.Canvas();
canvas.setPreferredSize(new java.awt.Dimension(800, 600));
add(canvas);
Keys keys = new Keys();
addKeyListener(keys);
pack();
while (true) {
events(keys);
if (exitAttempt) {
if (javax.swing.JOptionPane.YES_OPTION ==
showConfirmDialog("Do you want to Exit ?",
"Confirmation:", javax.swing.JOptionPane.YES_NO_OPTION,
javax.swing.JOptionPane.QUESTION_MESSAGE, null)) {
exit();
break; //while loop
}
exitAttempt = false;
}
}
dispose();
}
public void triggerCloseEvent() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
dispatchEvent(closeEvent);
}
});
}
public int showConfirmDialog(java.lang.Object message,
java.lang.String title, int optionType, int messageType,
javax.swing.Icon icon) {
return javax.swing.JOptionPane.showConfirmDialog(
this, message, title, optionType, messageType, icon);
}
public boolean exit() {
setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
return true;
}
public void events(Keys keys) {
System.out.println((keys.getPressed())[java.awt.event.KeyEvent.VK_ESCAPE]);
if ((keys.getPressed())[java.awt.event.KeyEvent.VK_ESCAPE]) {
triggerCloseEvent();
}
}
}
interface Events {
public void events(Keys keys);
}
class Keys implements java.awt.event.KeyListener {
private final boolean[] pressed;
public Keys() {
pressed = new boolean[256];
}
public void keyTyped(java.awt.event.KeyEvent event) {}
public void keyPressed(java.awt.event.KeyEvent event) {
pressed[event.getKeyCode()] = true;
}
public void keyReleased(java.awt.event.KeyEvent event) {
pressed[event.getKeyCode()] = false;
}
public boolean[] getPressed() {
return pressed;
}
}
I have a simple JFrame that asks a user for a confirmation to exit when they click X to close the window, this works fine
Your design is incorrect.
You should NOT have a while (true) loop.
GUI's are event driven. You create the frame and make it visible. That is the end of the code in your main() method or constructor. The GUI will then sit there forever doing nothing.
However, eventually, the user will then generate events that the GUI responds to.
This means that the code to display the JOptionPane should be moved to the windowClosing() method of your WindowListener.
See: Closing an Application for some basics and helpful classes to use.
I also wanted the user to be presented with the same option if they also pressed the escape key
Don't use a KeyListener.
Swing was designed to be used with Key Bindings.
You can use the ExitAction contained in the Closing an Application link when creating your key bindings:
KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
InputMap im = frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(escapeKeyStroke, "escape");
frame.getRootPane().getActionMap().put("escape", new ExitAction());
Read the Swing tutorial. There are section on :
How to Uuse Key Bindings
How to Use Actions
to help explain how the above suggestions work.
The tutorial examples will also show you how to better structure your code and note that the never use a while (true) loop.

Popup a compulsive window that the user can only interact with by Java Swing

So compulsive window here means like, I currently have interface(1) with a button, I click the button and it gives me a popup. I want this popup to be the only window that the user can interactive, so the user in this case cannot interact with interface(1). Think it like you are saving a Word doc, when you choose the file location to save this Word doc, you cannot modify the content of this Word doc. And that file saving window is what I want.
Currently I have a custom popup:
public class InputPopup {
private int closeflag;
private JFrame popup;
...
public int getCloseflag() {return closeflag;}
public void close(){
System.exit(0);
}
public void run() {
EventQueue.invokeLater(() -> {
try {
popup.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
And this is what I did in the button listener
InputPopup popup = new InputPopup(wordLabel.getText(), description.getText());
popup.run();
int flag = popup.getCloseflag();
while (flag != 1) {
flag = popup.getCloseflag();
}
popup.close();
Of course that does not work. Anyone has any idea on how to achieve that effect?

Java - Listen for copy and paste from clipboard

( 1 ) Is there a way to listen for any clipboard updates (including Ctrl+C/X, PrtSc (screenshot) and changes made by other programs) in Java? I have tried this:
Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
System.out.println("Copy detected");
}
});
This handles Ctrl+C changes well but doesn't notice changes which are not made by user manually, e.g. by screenshotting software or PrtSc button.
( 2 ) Is there a way to listen for paste actions (Ctrl+V, "paste" button, etc.)? I want something like that (or just with similar functionality):
// ...
#Override
public void prePaste(PasteEvent e) {
System.out.println("Paste detected");
e.cancel(); // reject the paste (so that user's Ctrl+V pastes nothing)
}
// ...
one way to capture when things are pasted into composites is to add a Listener "addKeyListener".
Java 8
KeyAdapter keyAdapter = new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent keyEvent)
{
if(((keyEvent.getModifiers() & InputEvent.CTRL_MASK) != 0) && (keyEvent.getKeyCode() == KeyEvent.VK_V))
{
String text = null;
try
{
text = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
System.out.println(text);
}
catch(Exception e)
{
e.printStackTrace();
}
keyEvent.consume();
}
}
};
stringTF.addKeyListener(keyAdapter);
for java over version 9 you can use the following condition
if(((keyEvent.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) && (keyEvent.getKeyCode() == KeyEvent.VK_V))
{
// Code ....
}

Input hint disappearing on mouseclick when component disabled

Thanks to the very helpful post by Bart Kiers in someone else's post, I have managed to get my input hints working. Hurray! Unfortunately I can't seem to get a small glitch to stop occurring.
During the normal course of operation, the HintTextFields are disabled and enabled to allow or disallow edits. The input hint should only show when the field is empty and not selected, but when I left click the boxes, even when disabled and containing text, the text disappears in favor of the hint. Then, when I click on something else, I lose the contents entirely.
I have added an extra bit to the if then statements regarding gaining and losing focus to prevent it from running that code if the component is disabled, but the problem still occurs. It must be some small interaction with the JTextField class (or maybe FocusListener?). I have also tried getParent() in favor of this in that clause, in case I was misunderstanding the 'this' keyword, but that didn't help. The class below:
class HintTextField extends JTextField implements FocusListener {
private final String hint;
private boolean showingHint;
public HintTextField(final String hint) {
super(hint);
this.hint = hint;
this.showingHint = true;
super.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
if(this.getText().isEmpty() && this.isEnabled()) {
super.setText("");
showingHint = false;
}
}
#Override
public void focusLost(FocusEvent e) {
if(this.getText().isEmpty() && this.isEnabled()) {
super.setText(hint);
showingHint = true;
}
}
#Override
public String getText() {
return showingHint ? "" : super.getText();
}
}
Original post if anyone wants to go upvote the wonderful Bart Kiers.
Java JTextField with input hint
Also, here is the initialization. This started as a JDeveloper gui.
startDateField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
startDateField.setToolTipText(notes);
startDateField.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
startDateField.setMaximumSize(new java.awt.Dimension(2, 16));
startDateField.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
startDateFieldMouseClicked(evt);
}
});
private void startDateFieldMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_startDateFieldMouseClicked
if (SwingUtilities.isRightMouseButton(evt)) {
editNote();
}
}
public void editNote() {
int selected = -1;
for (int a = 0; a < spinner.bitem.bldg.stallArray[1].length; a ++) {
if (spinner.bitem.bldg.stallArray[1][a].equals(stallName)) {
selected = a;
}
}
String oldNote = notes;
JTextField xField = new JTextField(oldNote);
xField.setPreferredSize(new Dimension(200,30));
JPanel myPanel = new JPanel();
myPanel.add(new JLabel("Note:"));
myPanel.add(xField);
int result =
JOptionPane.showConfirmDialog(this, myPanel, "Please enter note.",
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
String note = xField.getText();
if (!note.equals(oldNote)) {
notes = note;
spinner.bitem.bldg.stallArray[9][selected] = notes;
spinner.bitem.master.sendNoteDataToSQL(spinner.bitem.bldg.buildingName, spinner.bitem.bldg.stallArray[1][selected], notes);
spinner.updateScreen();
}
}
}

DocumentListener Validation Error in MVC Application

I am making a swing MVC application , to know the intricacies of GUI design using the Swing Framework . My JDK Version is 7 and I have a simple application that contains a dialog having a textfield for storing the path to a file , a browse button , 2 textfields for user id and password and 2 buttons for Update and Cancel functionalities.
Clicking on these buttons simply shows a dialog with either Update or Cancel message on it.
I planned to use DocumentListener to validate the textfield components.
In the UI i have the following code to create the 2 textfields :
public JPasswordField getMyPasswordField() {
if(myPasswordField == null)
{
myPasswordField = new JPasswordField();
myPasswordField.setBounds(133, 93, 163, 21);
myPasswordField.getDocument().putProperty("Owner", "myPasswordField");
}
return myPasswordField;
}
public JTextField getMyUserNameField() {
if(myUserNameField== null)
{
myUserNameField = new JTextField();
myUserNameField.setBounds(133, 66, 163, 21);
myUserNameField.getDocument().putProperty("Owner", "myUserNameField");
}
return myUserNameField;
}
In the controller I used the following code :
myReferenceUI.getMyUserNameField().getDocument().addDocumentListener(this);
myReferenceUI.getMyPasswordField().getDocument().addDocumentListener(this);
And in the method implementation I wrote the following :
public void insertUpdate(DocumentEvent e) {
Object owner = e.getDocument().getProperty("Owner");
changed(owner);
}
#Override
public void removeUpdate(DocumentEvent e) {
Object owner =e.getDocument().getProperty("Owner");
changed(owner);
}
#Override
public void changedUpdate(DocumentEvent e) {
Object owner =e.getDocument().getProperty("Owner");
changed(owner);
}
public void changed(Object e)
{
System.out.println(e.toString());
if( e.toString().equals("myUserNameField"))
{
if(myReferenceUI.getMyUserNameField().getText().equals("") )
{
myReferenceUI.getMyUpdateButton().setEnabled(false);
return ;
}
}
if( e.toString().equals("myPasswordField"))
{
if(myReferenceUI.getMyPasswordField().getText().equals("") )
{
myReferenceUI.getMyUpdateButton().setEnabled(false);
return ;
}
}
myReferenceUI.getMyUpdateButton().setEnabled(true);
}
My intent was to enable the update button only if the 2 textboxes for username and password have non null values.
The listener events fire properly and the update button is disabled in case of null entry in the username / password fields.
But after entering any value in these fields , if i press backspace and erase the text , the update button remains disabled.
What can i do to get rid of this condition ?
Use a DocumentListener that is aware of both the documents that you want to follow. For example:
private static class PasswordValidator implements DocumentListener {
private final Document[] documents;
private final JComponent component;
PasswordValidator(JComponent component, Document... docs) {
this.component = component;
documents = docs;
for (Document doc : docs) {
doc.addDocumentListener(this);
}
validate();
}
#Override
public void insertUpdate(DocumentEvent e) {
validate();
}
#Override
public void removeUpdate(DocumentEvent e) {
if (e.getDocument().getLength() == 0) {
component.setEnabled(false);
}
}
#Override
public void changedUpdate(DocumentEvent e) {
// Attribute change - ignore
}
private void validate() {
for (Document doc : documents) {
if (doc.getLength() == 0) {
component.setEnabled(false);
return;
}
}
component.setEnabled(true);
}
}
That particular implementation would then be used something like:
new PasswordValidator(myReferenceUI.getMyUpdateButton(), myReferenceUI.getMyUserNameField().getDocument(), myReferenceUI.getMyPasswordField().getDocument());
I got around my troubles by attaching PropertyChangedListeners to both my username and password fields and the following bit of code :
public void setUpdateButtonState()
{
if((myReferenceUI.getMyUserNameField().getText().equalsIgnoreCase("")
|| String.valueOf(myReferenceUI.getMyPasswordField().getPassword())
.equalsIgnoreCase("") ))
{
myReferenceUI.getMyUpdateButton().setEnabled(false);
}
else
{
myReferenceUI.getMyUpdateButton().setEnabled(true);
}

Categories

Resources