3 Replies Latest reply: Jan 25, 2011 7:45 AM by 833290 RSS

    Wrong characters in KeyEvents generated from input of barcode scanner

    833290
      Hi everybody, :-)

      I have a problem with KeyEvents coming from a barcode scanner. The issue seems to have creeped in somewhere between JSE 6u3 and 6u10, as in the former it works as expected and in the latter it does not. The problem persists still, we also tested it with 6u22 and 6u23 (all tests were performed on the same Windows XP machine). The actual test client is very simple, the application is only a JFrame containing a JTextField and a JTextArea.

      The barcode scanner we use connects via USB and has no special driver. The scanner already decodes the barcode that was scanned and "enters" characters in the focussed text field of the test application by emulating the Alt+NumPad behaviour (the character '5' being produced by the equivalent of holding Alt and entering "0053" on the NumPad).

      Now, what appears when the application is run in JSE 6u03 is the expected result:
      5@WM010$|
      5@WM010$|
      5@WM010$|
      5@WM010$|
      ...

      Here's the result for the same barcode when the application is run in JSE 6u10 (results for 6u23 are similar):
      5@WÞ10ä
      é@—M010$|
      5@W¥ð104|
      5°ùM0ó(▄♀
      5@W¥010$|
      é@WM010Ü\
      é@W¥010P\
      5@wy010$|
      5@m01Ð$▄
      )°W¥01è$|
      )@—0ÑÐ$|

      Well, at least it manages to get some characters right every time... ;-)

      The character values are wrong already when the KeyEvent for each is being created and posted to the EventQueue. But on the other hand, the problem is obviously tied to the JSE used, so it has to occur somewhere after Java receives the input and before a KeyEvent is generated. Since the errors are very random, we are guessing that it might be a timing problem.

      Between JSE 6u3 and 6u10, KeyEvent has received some new members (here with their typical values for my use case):
      #isSystemGenerated     true
      #primaryLevelUnicode     0     
      #rawCode     0     
      #scancode     0     
           
      Maybe the problem could have been introduced in the same changeset? Or maybe the values observed are meaningful in a way?

      Can anybody enlighten me, or give me a hint of any kind? I already scoured the bug database but did not find anything.

      Thanks! Any help is appreciated!

      Regards, Lars
        • 1. Re: Wrong characters in KeyEvents generated from input of barcode scanner
          828820
          Have you verified the default character set?
          • 2. Re: Wrong characters in KeyEvents generated from input of barcode scanner
            833290
            @mriem: Yes, I did. In all cases, it is "windows-1252". And moreover, if it were a problem with the default character set, it would not show the random behaviour it does.

            I also managed to create a reproducer that shows the behaviour:
            import static java.awt.event.KeyEvent.*;
            
            import java.awt.*;
            import java.util.*;
            
            import javax.swing.*;
            
            public class ScannerTest {
            
                 private static final String TEST = "5@WM010$|";
                 private static final int DELAY = 50;
                 private static final Map<Character, int[]> ALT_CODES = new HashMap<Character, int[]>();
            
                 static {
                      ALT_CODES.put('5', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD5, VK_NUMPAD3 });
                      ALT_CODES.put('@', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD6, VK_NUMPAD4 });
                      ALT_CODES.put('W', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD7, VK_NUMPAD7 });
                      ALT_CODES.put('M', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD8, VK_NUMPAD7 });
                      ALT_CODES.put('0', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD4, VK_NUMPAD8 });
                      ALT_CODES.put('1', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD4, VK_NUMPAD9 });
                      ALT_CODES.put('$', new int[] { VK_NUMPAD0, VK_NUMPAD0, VK_NUMPAD3, VK_NUMPAD6 });
                      ALT_CODES.put('|', new int[] { VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD4 });
                 }
            
                 public static void main(String[] args) throws Exception {
                      System.out.println(java.nio.charset.Charset.defaultCharset().name());
                      final int delay = DELAY;
                      final JFrame frame = new JFrame("ScannerTest");
            
                      SwingUtilities.invokeAndWait(new Runnable() {
                           @Override
                           public void run() {
                                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                                JScrollPane scrollPane = new JScrollPane(new JTextArea());
                                scrollPane.setPreferredSize(new Dimension(300, 600));
                                frame.add(scrollPane);
                                frame.pack();
            
                                frame.setVisible(true);
                           }
                      });
            
                      new Thread() {
                           @Override
                           public void run() {
                                try {
                                     Robot robot = new Robot();
                                     for (int c = 0; c < 1000; c++) {
                                          if (frame.isActive()) {
                                               for (int i = 0; i < TEST.length(); i++) {
                                                    int[] codes = ALT_CODES.get(TEST.charAt(i));
            
                                                    if (frame.isActive()
                                                              && !(codes == null || codes.length == 0)) {
                                                         robot.keyPress(VK_ALT);
                                                         
                                                         for (int code : codes) {
                                                              robot.keyPress(code);
                                                              robot.keyRelease(code);
                                                         }
                                                         robot.keyRelease(VK_ALT);
                                                    }
                                                    robot.delay(delay);
                                               }
                                               robot.keyPress(VK_ENTER);
                                               robot.keyRelease(VK_ENTER);
                                          } else {
                                               c--;
                                               try {
                                                    Thread.sleep(delay);
                                               } catch (InterruptedException e) {
                                                    e.printStackTrace();
                                               }
                                          }
                                     }
                                } catch (AWTException e) {
                                     e.printStackTrace();
                                }
                           }
                      }.start();
                 }
            }
            • 3. Re: Wrong characters in KeyEvents generated from input of barcode scanner
              833290
              It definitely has to do with the timings, as the problem disappears when I set the robot.setAutoDelay(1); So to further evaluate which timings are causing the problems we face with our barcode scanners, I removed the auto-delay again and added robot.delay(1) statements instead as shown in the code snippet:
                for (int i = 0; i < TEST.length(); i++) {
                  int[] codes = ALT_CODES.get(TEST.charAt(i));
              
                  if (frame.isActive() && !(codes == null || codes.length == 0)) {
                    robot.keyPress(VK_ALT);
              //    robot.delay(1);
                    
                    for (int code : codes) {
                      robot.keyPress(code);
              !!!     robot.delay(1);
                      robot.keyRelease(code);
              !       robot.delay(1);
                    }
                    robot.keyRelease(VK_ALT);
                  }
              //  robot.delay(1);
                }
                robot.keyPress(VK_ENTER);
              //robot.delay(1);
                robot.keyRelease(VK_ENTER);
              //robot.delay(1);
              Tests show that the delays in the commented line are unimportant. Most important is the line prefixed by the *!!!,* with this delay 95% of the random behaviour ceases. The rest disappears when putting a delay in the line with the *!*

              However, with regards to the barcode scanner it looks like we are not able to parametrize the delay time or when to delay at all. So the only workaround that occurs to me is to use a JRE prior to 6u10.

              Any other ideas, anyone? I'd appreciate every sensible proposal...