Previous Page
Next Page

Recipe 6.1. Adding an Item to the Display List

Problem

You want to add a new display object to the display list so it appears on-screen.

Solution

Use the addChild( ) and addChildAt( ) methods from the DisplayObectContainer class.

Discussion

The Flash Player is composed of two main pieces that function together to form a cohesive unit, the ActionScript Virtual Machine (AVM) and the Rendering Engine. The AVM is responsible for executing ActionScript code, and the Rendering Engine is what draws objects on-screen. Because the Flash Player is composed of these two main pieces, drawing an object on the screen is a two-step process:

  1. The display object needs to be created in the ActionScript engine.

  2. The display object is then created in the rendering engine and drawn on-screen.

The first step is done by using the new operator to create an instance of the display object. Any object that is going to be added to the display list must be either a direct or indirect subclass of DisplayObject, such as Sprite, MovieClip, TextField, or a custom class you create (according to Recipe 6.4). To create a TextField instance you would use the following code:

var hello:TextField = new TextField(  );

The preceding line of code creates a TextField display object in the AVM, but the object is not drawn on the screen yet because the object doesn't exist in the Rendering Engine. To create the object in the Rendering Engine, the object needs to be added to the display list hierarchy. This can be done by calling the addChild( ) or addChildAt( ) method from a DisplayObjectContainer instance that is itself already on the display list hierarchy.

The addChild( ) method takes a single parameterthe display object that the container should add as a child. The following code is a complete example that demonstrates how to create an object in the AVM and then create the object in the Rendering Engine by adding it to the display list:

package {
  import flash.display.DisplayObjectContainer;
  import flash.display.Sprite;
  import flash.text.TextField;

  public class DisplayListExample extends Sprite {
    public function DisplayListExample(  ) {
      // Create a display object in the actionscript engine
      var hello:TextField = new TextField(  );
      hello.text = "hello";
      
      // Create the display object in the rendering engine
      // by adding it to the display list so that the 
      // text field is drawn on the screen
      addChild( hello );
    }
  }
}

Here the DisplayListExample class is the main application class for the .swf movie and it extends the Sprite class. Because of the class hierarchy described in Figure 6-2, the DisplayListExample is therefore an indirect subclass of DisplayObjectContainer and is capable of having multiple DisplayObject instances as children. This allows for the use of the addChild( ) method to add a display object as a child in the container.

A TextField display object is created in the DisplayListExample constructor, which creates the object inside the AVM. At this point, the object won't appear on-screen because the Rendering Engine doesn't know about it yet. It is only after the object is added to the display listvia the addChild( ) method callthat the TextField is displayed.

The addChild( ) and addChildAt( ) methods only add display objects as children of display object containers. They do not necessarily add display objects to the display list. Children are added to the display list only if the container they are being added to is on the display list as well.


The following code snippet demonstrates how the addChild( ) method doesn't guarantee that a display object is added to the display list. A container is created with some text inside of it, but because the container is not on the display list, the text is not visible:

// Create a text field to display some text
var hello:TextField = new TextField(  );
hello.text = "hello";

// Create a container to hold the TextField
var container:Sprite = new Sprite(  );
// Add the TextField as a child of the container
container.addChild( hello );

To make the text display on-screen, the text container needs to be added to the display list. This is accomplished by referencing a display object container already on the display list, such as root or stage, calling addChild( ), and passing in the text container display object. Both root and stage are properties of the DisplayObject class:

// Cast the special root reference as a container and add the 
// container that holds the text so it appears on-screen
DisplayObjectContainer( root ).addChild( container );

Display object containers are capable of holding multiple children. The container keeps a list of children internally, and the order of the children in the list determines the visual stacking order on-screen. Each child has a specific position in the list as specified by an integer index value, much like an array. Position 0 is the very bottom of the list and is drawn underneath the child at position 1, which is, in turn, drawn underneath the child at position 2, etc. This is similar to the depth concept you may be familiar with if you have prior Flash experience, but it's easier to manage. There are no gaps between position numbers. That is, there can never be children at position 0 and position 2 with an opening at position 1.

When a new child display object is added via the addChild( ) method, it is drawn visually on top of all of the other children in the container because addChild( ) places the child at the front of the children list, giving it the next highest position index. To add a child and specify where it belongs in the visual stacking order at the same time, use the addChildAt( ) method.

The addChildAt( ) method takes two parameters: the child display object to add, and the position in the stacking order that the child should use. Specifying a position of 0 causes the child to be added to the very bottom of the list and makes the child appear (visually) underneath all of the other children. If there was previously a child at the position specified, all of the children at and above the position index are shifted forward by one to allow the child to be inserted. Specifying an invalid position value, such as a negative value or a number greater than the number of children in the container, generates a RangeError and causes the child to not be added.

The following example creates three different colored circles. The red and blue circles are added with the addChild( ) method, making the blue circle appear on top because it was added after the red circle. After the two calls to addChild( ), the red circle is at position 0 and the blue circle is at position 1. The green circle is then inserted between the two with the addChildAt( ) method, specifying position 1 as the location in the list. The blue circle, previously at position 1, is shifted to position 2 and the green circle is inserted at position 1 in its place. The final result is the red circle at position 0 being drawn underneath the green circle at position 1, and the green circle being drawn underneath blue circle at position 2.

package {
  import flash.display.*;
  public class CircleExample extends Sprite {
    public function CircleExample(  ) {
      // Create three different colored circles and
      // change their coordinates so they are staggered
      // and aren't all located at (0,0).
      var red:Shape = createCircle( 0xFF0000, 10 );
      red.x = 10;
      red.y = 20;
      var green:Shape = createCircle( 0x00FF00, 10 );
      green.x = 15;
      green.y = 25;
      var blue:Shape = createCircle( 0x0000FF, 10 );
      blue.x = 20;
      blue.y = 20;
      
      // First add the red circle, then add the blue circle (so blue 
      // is drawn on top of red)
      addChild( red );
      addChild( blue );
      
      // Place the green circle between the red and blue circles
      addChildAt( green, 1 );
    }
    
    // Helper function to create a circle shape with a given color
    // and radius
    public function createCircle( color:uint, radius:Number ):Shape {
      var shape:Shape = new Shape(  );
      shape.graphics.beginFill( color );
      shape.graphics.drawCircle( 0, 0, radius );
      shape.graphics.endFill(  );
      return shape;
    }
  }
}

So far we've only talked about adding new items to the display list, but what happens when addChild( ) is used on a child that is already on the display list, as a child of another container? This is the concept of reparenting. The child is removed from the container that it currently resides in and is placed in the container that it is being added to.

When you reparent a display object, it is not necessary to remove it first. The addChild( ) method takes care of that for you.


The following example shows reparenting in action. A container is created to display red, green, and blue circles that are all added as children, and the container is added to the display list. Another container is created and added to the display list as well, and then the red circle is moved from the first container to the second. Because the second container is visually above the first container in the display list, all children in the second container appear on top of the children in the first container. This makes the red circle display ontop of the blue and green ones. The red circle was reparented from the first container to the second simply by calling the addChild( ) method.

package {
  import flash.display.*;
  public class DisplayListExample extends Sprite {
    public function DisplayListExample(  ) {
      // Create three different colored circles and
      // change their coordinates so they are staggered
      // and aren't all located at (0,0).
      var red:Shape = createCircle( 0xFF0000, 10 );
      red.x = 10;
      red.y = 20;
      var green:Shape = createCircle( 0x00FF00, 10 );
      green.x = 15;
      green.y = 25;
      var blue:Shape = createCircle( 0x0000FF, 10 );
      blue.x = 20;
      blue.y = 20;
      
      // Create a container to hold the three circles, and add the
      // circles to the container
      var container1:Sprite = new Sprite(  );
      container1.addChild( red );
      container1.addChild( green );
      container1.addChild( blue );
      
      // Add the container to the display list
      addChild( container1 );
      
      // Create a second container and add it the display list
      var container2:Sprite = new Sprite(  );
      addChild( container2 );
      
      // Reparent the red circle from container 1 to container 2,
      // which has the net effect of the red circle being drawn
      // on top of the green and blue ones.
      container2.addChild( red );
    }
    
    // Helper function to create a circle shape with a given color
    // and radius
    public function createCircle( color:uint, radius:Number ):Shape {
      var shape:Shape = new Shape(  );
      shape.graphics.beginFill( color );
      shape.graphics.drawCircle( 0, 0, radius );
      shape.graphics.endFill(  );
      return shape;
    }
  }
}

See Also

Recipes 6.2 and 6.4


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