Is AS3 Ready For Prime-Time? (part 2) – taterboy
July 30th, 2008 | Filed under: Flash, Flash AS2 to AS3, Flex, Tips
Is Flex AS3 and Flash AS3 The Same?
It is hard enough to learn a new language, but when you write code using logic based on a method that worked so well in Flex, but now in Flash you are getting errors telling you that the method does not exits. It can get a little frustrating.
In Flex I use the Canvas as a starting point for most components, it inherits properties and methods from Display Object, UIComponent, and Container classes. In Flash we use a MovieClip as our base, which inherits methods and properties from the DisplayObject and DisplayObjectContianer classes.
One of my favorite methods in Flex is container.getChildren() which returns an Array of DisplayObjects in a container. This method is not available to a DisplayObjectContainer, are they not both containers? Flash does not have a Container class, so a method like removeAllChildren() is also not available to Flash AS3.
One of the possible reasons could be that you can build custom artwork inside of a MovieClip and mc.numChildren will count MovieClips, DrawingObjects, TextFields, and geomShapes as children which may not be what you are expecting if you were to call mc.getChildren().
In AS2, you could loop thought all the objects in a MovieClip which was a really nice feature that is no more. A work around is to maintain an Array of objects placed into a MovieClip, that way methods like getChildren() and removeAllChildren() are easily emulated.
It would be nice to have a base ContainerObject that was exactly the same in Flex and Flash to base all of our components on. Kind of mesh of the MovieClip Class and Canvas Class. Wishful thinking I am sure.
The Class below automatically creates and maintains an array(childList) of child DisplayObjects in a targeted MovieClip. The sample uses that array to emulate the getChildren() and removeAllChildren() from Flex’s Container class.
package com.hdi.util { import flash.events.Event; public class ChildMonitor { private var targ:Object; public var childList:Array; private var pauseUpdate:Boolean; public function ChildMonitor(mc:Object):void{ targ = mc; init(); } private function init():void{ targ.addEventListener(Event.ADDED,addHandler); targ.addEventListener(Event.REMOVED,removeHandler); childList = new Array(); pauseUpdate = false; } private function addHandler(ev:Event):void{ childList.push(ev.target); } private function removeHandler(ev:Event):void{ if(!pauseUpdate){ for(var i:String in childList){ if(ev.target == childList[i]){ childList.splice(Number(i),1); } } } } public function pullAll():void{ pauseUpdate = true; for(var i:String in childList){ trace(childList[i].name + " / " + childList.length); targ.removeChild(childList[i]); } init(); } } } |
added pullAll() method to childMonitor Class
Sample Usage: import com.hdi.util.ChildMonitor; var cmt:ChildMonitor = new ChildMonitor(containerClip); trace(cmt.childList.length); //returns 0 containerClip.addChild(newMC); trace(cmt.childList.length); //returns 1 containerClip.removeChild(newMC); trace(cmt.childList.length); //returns 0 //or: cmt.pullAll(); trace(cmt.childList.length); //returns 0 |
source here
I modified the Class to use the two methods from the comments below (Ian and Lanny, Thanks) as they proved to be move efficient. Source updated.
package com.hdi.util { public class ChildMonitor { private var targ:Object; public var childListArr:Array; public function ChildMonitor(mc:Object):void{ targ = mc; init(); } private function init():void{ childListArr = new Array(); } public function get childList():Array{ var childListArr = new Array(); if(targ.numChildren > 0){ for (var i:int=0; i<targ.numChildren; i++) { childListArr.push(targ.getChildAt(i)); } } return childListArr; } public function pullAll():void{ while (targ.numChildren > 0) { targ.removeChildAt(0); } init(); } } } |
|
RSS feed for comments on this post. TrackBack URL
Is this not an adequate solution for removing all the children of a MovieClip? It’s not a native method, but it’s still only 3 lines of code (and perhaps only 1 if you don’t care for readability).
while (some_clip.numChildren > 0) {
some_clip.removeChildAt(0);
}
Comment by Ian Ford — July 30, 2008 @ 11:55 am
That certainly is simple and sweat, thanks.
Comment by taterboy — July 30, 2008 @ 12:04 pm
Flex needs a container class due to all the extra functionality such as styles, constraints, etc that Flex needs to do its advanced layout management.
This is much easier than maintaining your own child list:
function getChildren():Array {
var children:Array = [];
for (var i:int=0; i<numChildren; i++) {
children.push(getChildAt(i);
}
return children;
}
Comment by Lanny — July 30, 2008 @ 1:53 pm