Stage loses keyboard focus when SimpleButton is removed on click

This is an annoying issue (bug?) I came across in a recent AS3 FlexBuilder project which uses the SimpleButton class. If you add a KeyboardEvent listener to the stage, and have a SimpleButton that gets removed (or its parent is removed), the SimpleButton grabs the keyboard focus and disappears with it. This is illustrated by the following code:

package
{
   import flash.display.SimpleButton;
   import flash.display.Sprite;
   import flash.events.KeyboardEvent;
   import flash.events.MouseEvent;

   public class SimpleButtonBug extends Sprite
   {
      public var simpleButton:SimpleButton;

      public function SimpleButtonBug()
      {
         var buttonSprite:Sprite = new Sprite();
         buttonSprite.graphics.beginFill(0x000000, 1);
         buttonSprite.graphics.drawRect(50, 50, 100, 40);
         buttonSprite.graphics.endFill();

         simpleButton = new SimpleButton(buttonSprite, buttonSprite, buttonSprite, buttonSprite);
         simpleButton.addEventListener(MouseEvent.CLICK, simpleButton_clickHandler);
         addChild(simpleButton);

         stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
      }

      public function simpleButton_clickHandler(event:MouseEvent):void
      {
         trace(stage.focus);

         removeChild(simpleButton);

         trace(stage.focus);
      }

      public function keyDownHandler(event:KeyboardEvent):void
      {
         trace("key pressed!");
      }
   }
}

Give the Flash movie focus by clicking on it, then press a few keys – you should see “key pressed!” trace out. Click the fancy black button, then press a few keys – no trace. The second stage.focus trace still displays “[object SimpleButton]” indicating that the button still has focus, but as it is no longer on the stage the event fails to bubble up to the stage.

A workaround is to return the focus to the stage when the button is removed:

public function simpleButton_clickHandler(event:MouseEvent):void
{
   trace(stage.focus);

   removeChild(simpleButton);
   stage.focus = stage;

   trace(stage.focus);
}

In my case this was easily done by adding that line to my Screen superclass’s REMOVED_FROM_STAGE handler (as it was occurring when screens were being removed during navigation using SimpleButtons). However, I believe that if a display object is removed it should return focus to the stage.

Oh, and BTW – first post!

2 Comments

matthias  on March 5th, 2009

thanks for writing this up!

Focus  on March 1st, 2010

Thanks for this script!

Leave a Comment