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!

9 Comments

matthias  on March 5th, 2009

thanks for writing this up!

Focus  on March 1st, 2010

Thanks for this script!

Justin  on July 28th, 2010

Thanks, solved it for me.

Edi  on January 26th, 2011

Thanks!

Andy  on March 15th, 2011

Thanks!

Riley  on September 6th, 2011

Super useful thanks! I was really scratching my head over this one!

andrew  on November 28th, 2011

Worked, you rule!

J  on April 16th, 2012

I just wanted to upvote your article to let you know it helped but there was no option; so I comment.

+1 to you sir.

Julio Rodrigeus  on April 22nd, 2012

Thank you man!

Leave a Comment