Skip navigation
ec30
Currently Being Moderated

Keyboard input delay Flex/AIR

Mar 25, 2011 4:42 AM

I've build an AIR desktop app that uses an USB barcode scanner. To capture the token provided by the barcode scanner an input field is used.

 

When testing the barcode input was only partially captured by the scanner. This was caused by the barcode scanner's input coming in the fast. Increasing the key stroke delay of the barcode scanner (config tool from motorola) solved the problem however this is not ideal.

 

Does anyone has experience with this type of problems? What is an approach to solve this? Maybe by writing an Java compagnion app that captures the keyboard input?

 
Replies
  • Currently Being Moderated
    Mar 25, 2011 11:44 AM   in reply to ec30

    I assume the scanner is sending keyboard events.  Write a low-level test app

    to determine if the app is getting all of them.  Hook a keyDown event

    listener to the stage.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2011 5:30 AM   in reply to ec30

    Hi,

     

    I  came across the same issue, and it is a timing issue.

     

    It is fine scanning into notepad.

     

    I use the following to capture the event, as the last character should be chr(13) / "Enter"

     

    protected function Init():void

    {

    txtBarcode.setFocus();

    txtBarcode.addEventListener(KeyboardEvent.KEY_DOWN, keyUpHandler1);

    }

     

     

    private function keyUpHandler1(e:KeyboardEvent):void

    {

    switch(e.keyCode)

    {

    case Keyboard.ENTER:

    if (StringUtil.trim(txtBarcode.text) == "") { /*Do nothing;*/ }

    else

    {

    //Do Something

    }

    }

     

    The result scan looks like this (should be "1330834 0.2 1":

    1330834 0.

    1330834 0.2

    1330834 0.2

    1330834 0.2

    1330834 0

    1330834 0.

    1330834 0.

    1330834 0.2

    1330834 0.2

    1330834 0

    1330834 0.2 1

    1330834 0.2

     

    It only got the scan correctrly once!

     

    What the heck is going on, Adobe?

     

    There is a timing issue here, and I am sure that it is a bug, as other application do not suffer the same problem.

    Works in Java Application, Web page, Windows WPF and Windows Forms Application.

     

    The issue is Adobe Air Events capturing.

     

    Shaun O'Reilly

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2011 6:11 AM   in reply to webwarrior007

    The following is a possible solution:

     

    <?xml version="1.0" encoding="utf-8"?>

    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"

       xmlns:s="library://ns.adobe.com/flex/spark"

       xmlns:mx="library://ns.adobe.com/flex/mx"

       applicationComplete="Init()">

    <fx:Script>

    <![CDATA[

    import spark.events.TextOperationEvent;

    import mx.controls.Alert;

    import mx.events.FlexEvent;

    import mx.rpc.events.ResultEvent;

    import mx.utils.StringUtil;

     

    private var timer2:Timer = new Timer(500); //Trigger, 500ms

     

    protected function Init():void

    {

    txtBarcode.setFocus();

    txtBarcode.addEventListener(KeyboardEvent.KEY_DOWN, keyUpHandler1);

    timer2.addEventListener(TimerEvent.TIMER, getValue);

    }

     

    private function keyUpHandler1(e:KeyboardEvent):void

    {

    switch(e.keyCode)

    {

    case Keyboard.ENTER:

    if (StringUtil.trim(txtBarcode.text) == "") { /*Do nothing;*/ }

    else

    {

    timer2.start();

    }

    break;

    }

    }

     

    private function getValue(event:TimerEvent):void

    {

    txtScannedCodes.text = txtScannedCodes.text + txtBarcode.text + ", ";

    timer2.stop();

    txtBarcode.text = "";

    txtBarcode.setFocus();

    }

     

    ]]>

    </fx:Script>

    <fx:Declarations>

    <!-- Place non-visual elements (e.g., services, value objects) here -->

    </fx:Declarations>

    <s:Label x="23" y="20" text="Scan into text box below" fontSize="36"/>

    <s:TextInput x="23" y="62" width="461" fontSize="36" id="txtBarcode"/>

    <s:TextArea width="461" left="23" top="114" bottom="22" id="txtScannedCodes"/>

    </s:WindowedApplication>

     

     

     

    It works, but is not ideal.

     

    Shaun O'Reilly

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2011 11:00 AM   in reply to webwarrior007

    What happens if you use mx:TextInput/mx:TextArea instead of Spark versions?

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2011 5:34 PM   in reply to Flex harUI

    Isn't that going backwards?

     
    |
    Mark as:
  • Currently Being Moderated
    Feb 27, 2012 7:19 PM   in reply to ec30

    I'm having the exact same problem in my AIR app. I'm scanning in a barcode via a FlexEvent.Enter event. It works about 50% of the time. The other 50% of the time it pulls in a partial string. So, when I debug using Flash Builder, event.target.text is always chopped about 50% of the time.

     

    Like webwarrior, it works fine in Notepad...so its most definitly an AIR problem. Did anyone happen to find a way around this? I'm usuing Flex 4.5 with MATE.

     
    |
    Mark as:
  • Currently Being Moderated
    Feb 28, 2012 11:56 AM   in reply to ec30

    Ok, I think I fixed my problem. I'm using the WaspWDI4500 2D Barcode Scanner. I found out by reading the manual that there is a setting called USB Keystroke Delay. By default, it was set to no delay. This was causing the problem. All I had to do was scan the Medium Delay 20msec barcode to change the barcode setting.

     

    This fixed everything. The FlexEvent.ENTER now has time to figure out what was scanned in.

     
    |
    Mark as:
  • Currently Being Moderated
    Feb 28, 2012 1:43 PM   in reply to BobxMarley

    We had the same problem with barcode scanners, but the model we had did not allow for the delay.  What I determined was that the ENTER event was being fired when the enter key (or Ascii 13 in the USB stream) entered the input buffer, but the other characters didn't get inserted into the text field until they were processed out of the input buffer.  The solution I used was to fire off a timer in the ENTER event handler, and the processing I really wanted to do in the ENTER event handler was done in the TIMER event handler instead.  Our barcodes were fairly short, so 100 milliseconds worked for us as a timer interval.  I liked this solution because it was fairly easy to tune the delay to how things worked.

     

    Mark

     
    |
    Mark as:
  • Currently Being Moderated
    Feb 28, 2012 1:45 PM   in reply to oldMster

    BTW, we were using mx: at the time, and in a browser based flex app, not AIR, so this issue exists over all target environments.  If you search this discussion group, you should be able to find my original discussion, if the search is working today....

    Mark

     
    |
    Mark as:
  • Currently Being Moderated
    Jul 25, 2013 2:26 PM   in reply to ec30

    I just ran into this same problem. Our users are scanning barcodes from various labels using various types of scanners (changing the delay using scanner software wasn't an option). We also have to allow them to scan to a TextInput within a DataGrid, which created even more problems. There were 2 very interesting things I learned in coming up with a solution for this one:

     

    1. As mentioned previously, the scanner inputs the data so quickly that the enter key event is often processed before the change event for the text. I tried several solutions (like trying to force the change event before the enter key is processed), but learned that the best solution was just to add the delay as mentioned in previous posts.

     

    2. When adding to a DataGrid control, I learned that both the DataGrid's & the TextInput's key down events are fired by the same SystemManager event. Though you can override the TextInput's keyDownHandler, you can't override the DataGrid's because it's a private method. So, even though my delay was being processed in the TextInput, the DataGrid was forcing control away from it and moving to the next item in the grid. To get around this one, I had to stop propagation of the event from the TextInput, then re-start the DataGrid's event once the delay was complete. I also had to process a focus-out event to get it to move to the next item in the DataGrid.

     

    Here's the code I used inside a custom TextInput control to handle processing both stand-alone and inside a DataGrid:

     

    override protected function keyDownHandler(event:KeyboardEvent):void

    {

          // If the enter key was pressed, then we need to add a delay.

          // Barcode scanners quite often process the enter key before the TextInput

          // control has time to finish processing all the text. (e.g., Instead of

          // getting 12345 as a text entry, you could get 123 or 1234.)

          if (event.charCode == Keyboard.ENTER)

       {

               // If this is the first time we've processed the enter key, we need to

               // add the delay.

               if (_keyboardEvent == null)

          {

               _keyboardEvent = new KeyboardEvent(event.type, event.bubbles,

               event.cancelable, event.charCode, event.keyCode, event.keyLocation,

               event.ctrlKey, event.altKey, event.shiftKey);

               event.stopImmediatePropagation();

               barcodeTimer(_keyboardEvent);

                          return;

          }

               // If the enter key is pressed while we are still in the delay, ignore

               // it.

               else if (_keyboardEvent != null && _keyboardEvent != event)

          {

                         return;

          }

               // If the delay is complete, then we need to restart events related to

               // the enter key so the control is handled properly.

               else

          {

                    super.keyDownHandler(event);

     

                    // If the TextInput is inside a DataGrid, then we need to dispatch the

                    // DataGrid's key down event. We also need to make sure the proper

                    // focus change happens (since this was stopped in the original event

                    // propagation).

                    if (parent != null && parent.parent != null &&

               parent.parent is mx.controls.DataGrid)

            {

               parent.parent.dispatchEvent(event);

               dispatchEvent(new FocusEvent(FocusEvent.KEY_FOCUS_CHANGE, true,

                              false, null, event.shiftKey, Keyboard.TAB));

            }

            _keyboardEvent = null;

                    return;

          }

       }

          super.keyDownHandler(event);

    }

     

    /**

    * This is a copy of the keyboard event to be processed once the barcode

    * delay is complete.

    */

    private var _keyboardEvent:KeyboardEvent = null;

     

    /**

    * This method launches a timer of sufficient length to allow barcode

    * scanner text to be processed before it re-launches the keyboard event.

    *

    * @param event This is the key-down event to be restarted once the timer is

    * complete.

    */

    private function barcodeTimer(event:KeyboardEvent):void

    {

          var t:Timer = new Timer(30, 1); // 30 ms

       t.addEventListener(TimerEvent.TIMER,

               function():void

          {

               keyDownHandler(event);

          } );

       t.start();

    }

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points