views:

2851

answers:

3

I'd like to arrange things so that I have a chain of keyboard event handlers in my flex application, all of whom are queried when key down events occur. Basically, when a visual component is on screen, it is a candidate for handling a key press event. Something like this (clearly this is pseudocode):

<application handles_keys="F5, F6">
    <tabGroup>
        <tab1 handles_keys="pgup, pgdn">
            <control handles_keys="0,1,2,3,4,5,6,7,8,9" />
        </tab1>
        <tab2 handles_keys="pgup, left, right"/>
    </tabGroup>
</application>

I have a class written that will respond to the key events the way I want it to, so how do I register one or more instances of this class to have the results I want? Also, note that there are some situations where this class should receive events that would ordinarily be handled by a UI component. The TAB key is the main example; I have a few cases where I want my key down event handler to fire even when the focus is on a text field.

+2  A: 

The way you have your pseudocode setup right now, you'd have to subclass all the different containers and add a "handles_key" property to each one. You may want to externalize the functionality to a separate class like this:

<KeyHandler target="{tab1}" handlesKeys="pgup,left,right"/>

As for actually catching the events, you'll need to add a KeyboardEvent.KEY_DOWN listener on the UIComponent you're wanting to listen to. You'll need to set the useCapture argument of addEventListener() to true as well. This will let you capture the event and prevent it instead of the event hitting the object and bubbling up.

target.addEventListener(KeyboardEvent.KEY_DOWN, target_onKeyDown, true);

Inside your target_onKeyDown event, check to see if you have a match for one of your keys you want to handle and if there is a match, call event.stopImmediatePropagation() or event.preventDefault() depending on what you need to do.

The Flex 3 Language Reference gives a good explanation of event propagation and keyboard events:

http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html

Ben Johnson
+1  A: 

Hello.

  1. when the displayed object is added to screen then start listen for stage keyboard events

  2. when the object was removed from the screen the remove the keyboard event listener

  3. on keyboard events filter the events you need :)

The code for a Canvas class you need should look like this:

class MyCanvas extends Canvas
{

   public function MyCanvas(){
       super();
   }

   override protected function createChildren():void{
       super.createChildren();
       this.systemManager.stage.addEventListener(KeyboardEvent.KeyUp, onKeyUpHandler);
   }

   private function onKeyUpHandler(e:KeyboardEvent):void{
       // handle your code

       switch(e.charCode){
           case Keyboard.1:
           case Keyboard.2:
           case Keyboard.3:
           case Keyboard.4:
           case Keyboard.5:
           case Keyboard.6:
           case Keyboard.7:
           case Keyboard.8:
           case Keyboard.9:{
                   // do my stuff
                   break;
                 }
            case Keyboard.F1:{
                   // do other stuff
                   break;
                 }

           }

       }

   }   

   public function destroy():void{
       //don't forget to remove listeners for stupid flash garbage collector
       this.systemManager.stage.removeEventListener(KeyboardEvent.KeyUp, onKeyUpHandler);
   }

}

Ignore any miss-spells :D I wrote the code from my mind :))


TiMeister - Online Timesheet

Adrian Pirvulescu
A: 

The correct approach turns out to have been a global keyboard event manager, added as a key down listener to the stage when the application's creationComplete event is called. This then dispatches domain events for each keypress or combination thereof. Sadly, the filtering per-component model didn't work out.

I'm going to be porting this app to the Cairngorm framework, which should work really well once I'm done it.

Chris R