Previous Page
Next Page

Recipe 6.2. Removing an Item from the Display List

Problem

You want to remove an item from the display list and consequently remove it from the screen.

Solution

Use the removeChild( ) and removeChildAt( ) methods from the DisplayObectContainer class.

Discussion

Recipe 6.1 demonstrates how to add display objects to the display list using the addChild( ) and addChildAt( ) methods. To achieve the opposite effect and remove a child via one of these methods, use either the removeChild( ) or removeChildAt( ) method.

The removeChild( ) method takes a single parameter, which is a reference to the display object that should be removed from the container. If an object is supposed to be removed and it isn't a child of the container, an ArgumentError is thrown:

package {
  import flash.display.Sprite;
  import flash.text.TextField;
  import flash.events.MouseEvent;

  public class RemoveChildExample extends Sprite {
    
    // Create a local variable to store a reference
    // to the TextField so that we can remove it later
    private var _label:TextField;
    
    public function RemoveChildExample(  ) {
      _label = new TextField(  );
      _label.text = "Some Text";
      
      // Add the hello TextField to the display list
      addChild( _label );
      
      // When the mouse is clicked anywhere on the stage,
      // remove the label
      stage.addEventListener( MouseEvent.CLICK, removeLabel );
    }
    
    // Removes the label from this container's display list
    public function removeLabel( event:MouseEvent ):void {
      removeChild( _label );
    }
  }
}

The preceding code example creates a local variable label that stores a reference to the TextField within the class itself. This is a necessary step because the removeChild( ) method must be passed a reference to the display object to remove, so label is used to store the reference for later. If label were not available, extra work would be required to get a reference to the TextField to remove it, or the removeChildAt( ) method could be used instead.

In the case whenyou do not have a reference to the display object you want to remove, you can use the removeChildAt( ) method. Similar to the addChildAt( ) method, the removeChildAt( ) method takes a single parameterthe index in the container's list of child display objects to remove. The possible values for the index can range from 0 to numChildren 1. If an invalid index is specified, such as a negative value or a value greater than the number of children in the container, a RangeError is thrown and no child7 is removed. Adopting the previous code snippet to use removeChildAt( ) instead yields the following:

package {
  import flash.display.Sprite;
  import flash.text.TextField;
  import flash.events.MouseEvent;

  public class DisplayListExample extends Sprite {
    
    public function DisplayListExample(  ) {
      var label:TextField = new TextField(  );
      label.text = "Some Text";
      
      // Add the hello TextField to the display list
      addChild( label );
      
      // When the mouse is clicked anywhere on the stage,
      // remove the label
      stage.addEventListener( MouseEvent.CLICK, removeLabel );
    }
    
    // Removes the label from this container's display list
    public function removeLabel( event:MouseEvent ):void {
      // Only remove the label if it exists
      if ( numChildren > 0 ) {
        removeChildAt( 0 );
      }
    }
  }
}

The biggest change by switching to removeChildAt( ) is that you no longer need to declare label to store a reference to the TextField so it can be removed later. Instead, when label is added to the RemoveChildExample container, it is added at position 0. To remove the label display object, simply remove the child at position 0.

Removing a child display object does not delete it entirely. Instead, it just removes it from the container and prevents the object from being drawn. To completely delete the display object, set all references to the object to null.


If you want to remove all of a container's children, combine removeChildAt( ) with a for loop. Every container has a numChildren property that indicates how many display objects are in the container's display list. By looping one time for each child, you can remove each child based on its position in the container's child list. This is somewhat of a tricky process because of how the position value works.

Whenever a child is removed from a certain position, all of the other children with higher positions shift their position values down by one to eliminate the gap. For example, consider a container with three children at positions 0, 1, and 2. When the child at position 0 is removed, the child at position 1 shifts down to position 0 and the child at position 2 shifts down to position 1. Because the position values change every time a child is removed, there are two ways to handle the removal of all children:

  1. Always remove the child at position 0.

  2. Remove the children backward, starting from the end.

In the first case, because there will always be a child at position 0 as long as the display object has children, you can continue to remove what is at position 0 because it is a new child display object during each loop iteration.

In the second case, removing the very last child from the container does not cause any children to adjust their positions. Only children with a higher position value than what is removed are shifted down by one. The last child has the highest position value within the container; therefore, no other children need to have their positions adjusted.

The first approach is the one we recommend using, and has been implemented in the ascb.util.DisplayObjectUtilities class:

package ascb.util {
  import flash.display.*;
  public class DisplayObjectUtilities {
    // Remove all of the children in a container
    public static function removeAllChildren( 
                             container:DisplayObjectContainer ):void {
      
      // Because the numChildren value changes after every time 
      // you remove a child, save the original value so you can 
      // count correctly
      var count:int = container.numChildren;
      
      // Loop over the children in the container and remove them
      for ( var i:int = 0; i < count; i++ ) {
        container.removeChildAt( 0 );
      }
    }
  }
}

Using the DisplayObjectUtilities.removeAllChildren( ) method is relatively straight- forward, as shown here:

package {
  import flash.display.*;
  import ascb.util.DisplayObjectUtilities;  

  public class DisplayListExample extends Sprite {
    
    public function DisplayListExample(  ) {
      
      // Add some empty sprites
      addChild( new Sprite(  ) );
      addChild( new Sprite(  ) );
      
      // Remove all children from this container
      DisplayObjectUtilities.removeAllChildren( this );
      
      // Demonstrate that all children have been removed - displays: 0
      trace( numChildren );
    }
   
  }
}

See Also

Recipe 6.1


Previous Page
Next Page
Converted from CHM to HTML with chm2web Pro 2.85 (unicode)