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:
-
The display object needs to be created in the
ActionScript engine.
-
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
|