Reading from a Barcode Scanner in Swing - java

I have installed a bar-code scanner from Datalogic, with the goal of reading the bar-code into a java textfield. However, when I scan the bar code in Swing, the resulting text is garbage. I cannot use this. On standalone java.awt.TextField is works fine, but when I integrate this into my code, it also produces garbage non-mappable characters.
Don't know if I'll need a specific driver for JAVA,
I have tried converting the string from UTF-8 to ISO-88... to no avail.
Been looking at this since 2 days in-vain.
Any help will be greatly appreciated.
Thanks
-innocent

try resetting the scanner to remove all spurios characters/codes that might have been set up; i.e. according to the reference guide the scanner will send by default the barcode id for gs1-128 codes as an escape sequence, which might cause some trouble for swing
download the product reference guide from http://www.datalogic.com/eng/quickscan-i-lite-qw2100-pd-163.html
scan the barcode to enter programming mode
go to the relevant section and scan the codes to remove all preambles and to remove the aim label for all codes
you can also try the different types of keyboard emulation and codepage.

There is a problem with KeyEvents coming from a barcode scanner using ALT + NumPad method. Java generates KeyTyped events with random outputs when ALT key is pressed. The problem exists in the current versions of Java 7 and Java 8 JRE (I have tested it with JRE 7u67 and JRE 8u20 on Windows 8, Windows 7 and Ubuntu 14).
My solution is to register a KeyEventDispatcher that blocks the KeyEvents when the ALT method is active:
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new AltBugFixKeyEventDispatcher());
public class AltBugFixKeyEventDispatcher implements KeyEventDispatcher {
private int i = -1;
#Override
public boolean dispatchKeyEvent(KeyEvent ke) {
if (ke.isAltDown()) {
switch (ke.getID()) {
case KeyEvent.KEY_PRESSED:
if(ke.getKeyCode() == KeyEvent.VK_ALT){
i = 0;
}else if(Character.isDigit(ke.getKeyChar())){
i++;
}else{
i = -1;
}
break;
case KeyEvent.KEY_RELEASED:
break;
case KeyEvent.KEY_TYPED:
break;
}
if(i != -1){
return true;
}
}
return false;
}
}

Related

How to detect keyboard language?

For a (NetBeans) GUI in Java language below,
I want keyboard input language mode be automatically changed -
to Korean when the "K Box" gets focus (i.e., cursor is in "K Box"),
to English When the "E Box" gets focus (i.e., cursor is in "E Box")
(FYI, keyboard input language mode is changed by hitting right-ALT key).
If that is not going to be possible, I want to detect whether it is in English input mode or in Korean input mode. Then I'll make a label telling current input language mode to the users so they don't need to make mistake typing Korean in English mode.
I defined following method and using it to change keyboard language for a specific component. In the code 'ControlEnums.Languages' is my own enum type, so you may ignore it for the moment.
public static void setKeyboardLanguage(Component comp,
ControlEnums.Languages language)
{
try {
InputContext inCtx = comp.getInputContext();
Character.Subset[] subset = new Character.Subset[1];
if (language == KOREAN) {
// for Korean input mode
subset[0] = Character.UnicodeBlock.HANGUL_SYLLABLES;
} else {
// for English input mode
subset = null;
}
inCtx.setCharacterSubsets(subset);
} catch(Exception e) {
}
}
I found the above method 'setKeyboardLanguage' works pretty well. Does anyone have a better idea on my research?

How to add a KeyListener to a JPanel [duplicate]

How can I let my custom KeyListener listen for combinations of ALT (or CTRL for that matter) + more than one other key?
Assume I have 11 different actions I want the application to do, depending on a combination of keys pressed. ALT + 0 - ALT + 9 obviously don't pose any problems, whereas for ALT + 1 + 0 (or "ALT+10" as it could be described in a Help file or similar) I cannot find a good solution anywhere on the web (or in my head). I'm not convinced that this solution with a timer is the only possible way.
Thanks a million in advance for any suggestions!
Edit: Actions 0-9 + action 10 = 11 actions. Thanks #X-Zero.
You should not use KeyListener for this type of interaction. Instead use key bindings, which you can read about in the Java Tutorial. Then you can use the InputEvent mask to represent when the various modifier keys are depresed. For example:
// Component that you want listening to your key
JComponent component = ...;
component.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
java.awt.event.InputEvent.CTRL_DOWN_MASK),
"actionMapKey");
component.getActionMap().put("actionMapKey",
someAction);
See the javadoc for KeyStroke for the different codes you can use while getting the KeyStroke. These modifiers can be OR'ed together to represent various combinations of keys. Such as
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
java.awt.event.InputEvent.CTRL_DOWN_MASK
| java.awt.event.InputEvent.SHIFT_DOWN_MASK)
To represent when the Ctrl + Shift keys were depressed.
Edit: As has been pointed out, this does not answer you question but instead should just be taken as some good advice.
You can use KeyListener for this purpose by combining certain things. Look at the following example, which should be placed in an overridden keyPressed(KeyEvent e) method.
if (e.isControlDown() && e.getKeyChar() != 'a' && e.getKeyCode() == 65) {
System.out.println("Select All");
}
The string Select All will be displayed when Ctrl + a is pressed. The method e.isControlDown() checks whether the Ctrl key is pressed or not.
Similarly, the Alt key combinations can be done with the same method by using e.isAltDown() method.
The logic behind this is, e.getKeyChar() returns the character of the key presses & e.getKeyCode() returns its ASCII code. When Ctrl is pressed and hold, the e.getKeyChar() won't return a and e.getKeyCode() will be the same 65. Hope you understand this. Feel free to ask more.
ALT + 1 + 0 (or "ALT+10" as it could be described in a Help file or similar)
seems to clash with (from one of your comments):
So for example if the user wants to change data in column 11 (which would be called "10"), s/he'd press ALT + 1 + [lets go of both ALT and 1] 0.
Assuming that ALT+10 means 'Pressing ALT, pressing and releasing 1, pressing and releasing 0, releasing ALT' I propose trying this:
In keyPressed, listening for the ALT key, activate a boolean flag, isAltPressed, and create a buffer to hold key presses that occur (a string, say).
In keyTyped, if isAltPressed is active, append key codes to the buffer.
In keyReleased, listening for ALT again, open a conditional querying the buffer and executing actions.
public void keyPressed (KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_ALT){
buffer = ""; //declared globally
isAltPressed = true; } //declared globally
}
public void keyTyped (KeyEvent e){
if (isAltPressed)
buffer.append (e.getKeyChar());
}
public void keyReleased (KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_ALT){
isAltPressed = false;
if (buffer.equals (4948)) //for pressing "1" and then "0"
doAction();
else if (buffer.equals(...))
doOtherAction();
...
}//if alt
}
import java.awt.*;
import java.awt.event.*;
class KDemo
{
public static void main(String args[])
{
Frame f = new Frame();
f.setSize(500,500);
f.setVisible(true);
f.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
AWTKeyStroke ak = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
if(ak.equals(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_F4,InputEvent.ALT_MASK)))
{
System.exit(0);
}
}
});
}
}
I would suggest that instead of using key combinations, consider some input field when the window isVisible() and is focused. The field can be hidden, like Windows' File explorer hidden filename search (enter a directory, type the filename and the correspondence is focused), or is visible, like in Ubuntu.
Key combinations are not designed for including more than one key other than modifiers, although you may be able to achieve this.
I think there's a simpler way which I am using. If the KeyEvent is ev then if you investigate:
(int)ev.getKeyChar()
you find that ctrl-a is 1, ctrl-b is 2 and so on. I wanted to use ctrl-s for save. So I just use:
(((int)ev.getKeyChar())==19)
to detect it. No idea why, but it works fine whereas:
ev.isControlDown() && ev.getKeyChar()=='s'
does not.

How to handle keypresses for a calculator made in Java?

I've made a simple calculator using an tutorial online using Netbeans and it works fine when clicking the respective buttons, however I'm looking to improve it by allowing keypresses to work.
What I'd like is for the numbers 0-9 to work, +, -, *, / and enter as =.
I think I know how to do it, but can't seem to figure it out.
For example, the code for my 1 button is:
private void btnOneActionPerformed(java.awt.event.ActionEvent evt) {
String btnOneText = txtDisplay.getText() + btnOne.getText();
txtDisplay.setText(btnOneText);
}
So for the keypress I created a keypress event but I'm not sure what the code is. I assume it's something like this:
private void jPanel1KeyPressed(java.awt.event.KeyEvent evt) {
//if statement to check if 1 key has been pressed, then execute rest of code
String btnOneText = txtDisplay.getText() + btnOne.getText();
txtDisplay.setText(btnOneText);
}
However I'm probably completely wrong. Any help?
You can use either of KeyListener or KeyBindings depending on your usage.
Since you are designing a simple calculator, there is no harm with KeyListener since there are not many controls.
Demo code for the same is.
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_0:
//handle 0 press
break;
case KeyEvent.VK_1:
// handle 1 press
break;
case KeyEvent.VK_2:
// handle 2 press
break;
case KeyEvent.VK_3 :
// handle 3 press
break;
//
}
}
You can find the keycodes here : http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyEvent.html

Java swt KeyListener "solution" barcode reading

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.
User is typing some info, (alpha numerical)
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
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:
waits for number input otherwise does nothing
if 1st number is inserted it is looping in if condition until either 200ms is reached or '\r\n` is received
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;
}
}
});
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();
}
}
...
}

Why does this code have a "one off error"?

I am building a GWT component to behave much like the comments box here on stackoverflow, and other sites. I am trying to register listeners for KeyPress, Change and ONPASTE events that will update my status line with number of characters remaining, etc.
It works except it is always one character behind the actual number of characters in the text area. I set the max number of characters to 10. When I type the first character it still says, "10 characters remaining". It doesn't update the status line until I type the second character and then it is one off, it says 9 characters remaining when the second character is typed.
When I BACKSPACE or DELETE, it is also one off, when there are no characters it still says "9 characters remaining" until I press the BACKSPACE or DELETE a second time.
I am getting this behavior in both Firefox, Chrome and Internet Explorer on Windows. So I think I am not registering something correctly.
I know this has something to do with when the events are getting fired, but I have spend hours on trying to diagnose this behavior and have run out of ideas.
Here is where I am registering the event handlers, the complete code is BoundedTextAreaWithFeedback.
private void registerHandlers()
{
final BoundedTextAreaWithFeedback outer = this;
this.textArea.addChangeHandler(new ChangeHandler()
{
public void onChange(final ChangeEvent changeEvent)
{
outer.validate();
}
});
this.textArea.addKeyPressHandler(new KeyPressHandler()
{
public void onKeyPress(final KeyPressEvent keyPressEvent)
{
outer.validate();
}
});
this.panel.addFocusHandler(new FocusHandler()
{
public void onFocus(final FocusEvent focusEvent)
{
outer.textArea.setFocus(true);
}
});
// capture paste events
this.textArea.sinkEvents(Event.ONPASTE);
}
Here is the validate() method.
private boolean validate()
{
final boolean isValid;
final int len = this.textArea.getText().length();
if (len < this.minLength)
{
this.status.setText("Enter at least " + this.minLength + " characters.");
this.status.setStyleName("input-status-underflow");
isValid = false;
}
else if (len > this.maxLength)
{
this.status.setText(this.maxLength - len + " characters remaining");
this.status.setStyleName("input-status-overflow");
isValid = false;
}
else
{
this.status.setText(this.maxLength - len + " characters remaining");
this.status.setStyleName("input-status-ok");
isValid = true;
}
return isValid;
}
I just started adding every addXXXHandler() until one worked.
this.textArea.addKeyUpHandler(new KeyUpHandler()
{
public void onKeyUp(final KeyUpEvent event)
{
outer.validate();
}
});
Seems to have done the trick.
Here is the working code, CTRL-V and paste from context menu also work now.
Try using a DeferredCommand to execute the validation code. I believe the problem is that when the event is firing, they character is not yet added to the text area. The DeferredCommand will not execute until any pending event handlers have finished, allowing the length of the text to be calculated correctly.
See this question for an example of using a DeferredCommand.

Categories