AS3 event handler in child object is not firing
Maybe I missed some point along the way when learning AS3 and event handling. Anyways, the loader's complete event (onLoad) is not firing for the loader within the imgManager object. If I copy the same code in the main class and ask it to fire the same event from within itself it works fine. Here is my code:
public class ImageScroller extends Sprite
{
public function ImageScroller()
{
var imgMan:ImageManager = new ImageManager();
var v:Vector.<String> = new Vector.<String>();
v[0] = "../assets/apache_pb.gif";
imgMan.LoadImages(v);
addChild(imgMan.loadedImages[0]);
}
}
public class ImageManager
{
public var _loader:Loader;
private var _urlRequest:URLRequest;
private var _loadedImages:Vector.<Bitmap>;
public var bo:Boolean = false;
public function ImageManager()
{
_loader = new Loader();
_loadedImages = new Vector.<Bitmap>();
}
public function LoadImages(v:Vector.<String>):void
{
for(var i:int = 0; i < v.length;i++)
{
_loader.load(new URLRequest(v[i]));
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad);
}
}
private function onLoad(e:Event):void
{
开发者_运维知识库 bo = true;
var bmp:Bitmap = (Bitmap)(e.target.content);
_loadedImages[0] = bmp;
}
public function get loadedImages():Vector.<Bitmap>
{
return _loadedImages;
}
}
}
I rewrote your code and believe the following is the solution to you problem:
Main.as:
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
public function Main()
{
init();
}// end function
private function init():void
{
var imageScroller:ImageScroller = new ImageScroller("images/image1.jpg",
"images/image2.jpg",
"images/image3.jpg");
addChild(imageScroller);
}// end function
}// end class
}// end package
ImageScroller.as
package
{
import flash.display.Sprite;
import flash.events.Event;
public class ImageScroller extends Sprite
{
private var _urls:Array;
private var _imageManager:ImageManager;
public function ImageScroller(...urls:Array)
{
_urls = urls;
init();
}// end function
private function init():void
{
_imageManager = new ImageManager();
_imageManager.load(_urls);
_imageManager.addEventListener(Event.COMPLETE, onImageManagerComplete);
}// end function
private function onImageManagerComplete(e:Event):void
{
addChild(_imageManager.bitmaps[0]);
}// end function
}// end class
}// end package
ImageManager.as
package
{
import flash.display.Bitmap;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
public class ImageManager extends EventDispatcher
{
private var _urls:Array;
private var _bitmaps:Vector.<Bitmap>;
private var _loadedBitmapCount:int;
public function get bitmaps():Vector.<Bitmap>
{
return _bitmaps;
} // end function
public function ImageManager()
{
init();
}// end function
public function load(urls:Array):void
{
for each(var url:* in urls)
{
if(!(url is String))
throw new ArgumentError("Arguments must be of type String");
}// end for
_urls = urls;
for(var i:int = 0; i < _urls.length; i++)
{
var loader:Loader = new Loader();
loader.load(new URLRequest(_urls[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
} // end for
} // end function
private function init():void
{
_bitmaps = new Vector.<Bitmap>();
}// end function
private function onLoaderComplete(e:Event):void
{
if(++_loadedBitmapCount >= _urls.length)
{
dispatchEvent(new Event(Event.COMPLETE));
}// end if
var bitmap:Bitmap = (Bitmap)(e.target.content);
bitmaps.push(bitmap);
}// end function
}// end class
}// end package
[UPDATE]
The problem you where having was that you tried to access the loaded images before they were loaded.
imgMan.LoadImages(v);
addChild(imgMan.loadedImages[0]);
What you needed was an event listener that would listen for your ImageManager
object to dispatch an event when it had loaded all the images. To do this, I first changed your ImageManager
class from an Object
to an EventDispatcher
.
public class ImageManager extends EventDispatcher
Now the ImageManager
has the two methods needed to dispatch an event and listen for it which are respectively the dispatchEvent()
and addEventListener()
methods.
Next I changed the code so that condition would test to see if all the images where loaded on each call to the onLoaderComplete
event handler when the loader
objects when the event listeners call it. This was done with the help of the _loadedBitmapCount
integar property that incremented on each call then tested its value against the length of the _urls
array property's length property. When the condition was met, the ImageManager
EventDispatcher
object would call its dispatchEvent()
method and dispatch an Event.COMPLETE
event object.
public function load(urls:Array):void
{
// ...
for(var i:int = 0; i < _urls.length; i++)
{
var loader:Loader = new Loader();
loader.load(new URLRequest(_urls[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
} // end for
} // end function
//...
private function onLoaderComplete(e:Event):void
{
if(++_loadedBitmapCount >= _urls.length)
{
dispatchEvent(new Event(Event.COMPLETE));
}// end if
}// end function
Finally I changed the code in the ImageScroller
class by adding an event listener that listened for the ImageManager
object to dispatch the Event.COMPLETE
event object. When this would happen and the onImageManagerComplete()
event handler was called, now the loaded images were accessible, because now they had been infact loaded.
private function init():void
{
_imageManager = new ImageManager();
_imageManager.load(_urls);
_imageManager.addEventListener(Event.COMPLETE, onImageManagerComplete);
}// end function
private function onImageManagerComplete(e:Event):void
{
addChild(_imageManager.bitmaps[0]);
}// end function
If there is anything you didn't understand or want to ask me about, just add a comment to this answer.
精彩评论