<

Finding a DisplayObject at any depth of the AS3 Display List

Published on
19,925 Points
13,325 Views
1 Endorsement
Last Modified:
Approved
Sometimes you know that one object has a specific child in it, but you can't find the child.

This happened to me when I was trying to code some actionScript to make a toolbar work with its embedded buttons.  My partner had created the toolbar using a third party Flash class, and I knew the name of the toolbars and the buttons, but I couldn't access the button.  No syntax I tried would let me get to it.  I tried myToolbar.myButton, myToolbar["myButton"] and myToolbar.getChildByName( "myButton" ), but none of them gave me the button.  getChildByName returned null, which I knew meant that myButton wasn't a child of myToolbar.  Iterating through all the children of myToolbar, all I found were a lot of objects named with "instance" followed by a number.

We checked the work my partner had done.  He had properly named each button, but I wasn't finding it where I thought I would.

To make a long day of research short, it eventually became obvious that the button wasn't an immediate child of the toolbar.  The "instance" names seem to be pretty common to Flash; they are generated frequently in objects designed in Flash.

This question on EE got me pointed in the right direction.  I used the code from ugeb to dump the display lists of myToolbar.  The third-party toolbar software apparently added the button three levels deep.  We started doing a horrible thing - hard-coding to the "instance" variables.  This produced some ugly code:

var i117:DisplayObjectContainer = myToolbar.getChildByName( "instance117" ) as DisplayObjectContainer;
var i189:DisplayObjectContainer = i117.getChildByName( "instance189" ) as DisplayObjectContainer;
var i288:DisplayOjbectContainer = i189.getChildByName( "instance288" ) as DisplayObjectContainer;
var myButton:DisplayObject = i288.getChildByName( "i288" ) as DisplayObject;

Open in new window


This worked on my machine, but is only acceptable if you never add any more children to the display list.  This is not robust, and therefore not good.  I realized that I could modify the code that traces each child in the display list to simply find the child you want.  The code below shows the function I used:

function findChild( dispobj:DisplayObjectContainer, childname:String ):DisplayObject
{
    if (dispobj == null)
    {
        dispobj = this;
    }
 	
    for (var j:int = 0; j < dispobj.numChildren; ++j)
    { 
        var obj:DisplayObject = dispobj.getChildAt( j ) as DisplayObject;
        if (obj.name == childname)
        {
            return obj;
        }
        if (obj is DisplayObjectContainer)
        {
            var doc:DisplayObjectContainer = obj as DisplayObjectContainer;
            if (doc.numChildren > 0)
            {
                var ret:DisplayObject = findChild( doc, childname );
                if (ret != null)
                {
                    return ret;
                }
            }
        } 
    }
    return null;
}

Open in new window

Usage is simple, e.g.
var myButton:DisplayObject = findChild( myToolbar, "myButton" );

This will run through every child of myToolbar, looking for one named "myButton".  If it doesn't find any, it will return null.
If you want to search the entire displaylist, simply pass null as the first argument.

By using this code, I made my code much more robust, and got the buttons hooked up easily.  Any time you can't find a DisplayObject where it should be, you can use this to find it for you.
1
Author:Carnou
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free