views:

695

answers:

2

Hello.

I am learning ActionScript 3.0 and I am seeing this paradigm often:

package util
{
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.net.URLRequest;
    import flash.events.Event;

    public class BitmapLoader extends Sprite
    {
     private var loader:Loader = new Loader();

     private var filePath:String;

     public function BitmapLoader(filePath)
     {
      this.filePath = filePath;

      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeListener);
     }

     public function load():void
     {
      loader.load(new URLRequest(filePath));
     }

     private function completeListener(event:Event):void
     {
      addChild(loader);
     }
    }
}

What I would like to be able to do is get the object back rather that treat the loader as a DisplayObject. I will post my idealized version in the hopes that it will best explain what I would like to do.

package util
{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.net.URLRequest;
    import flash.events.Event;

    public class BitmapLoader
    {
     private var hasLoaded:Boolean = false;
     private var loader:Loader = new Loader();

     private var filePath:String;
     private var bitmap:Bitmap;

     public function BitmapLoader(filePath)
     {
      this.filePath = filePath;

      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeListener);
     }

     public function load():Bitmap
     {
      loader.load(new URLRequest(filePath));

      while(!hasLoaded);

      return bitmap;
     }

     private function completeListener(event:Event):void
     {
      bitmap = new Bitmap(Bitmap(LoaderInfo(event.target).content).bitmapData);
      hasLoaded = true;
     }
    }
}

What I'm missing is why the while loop never exits. Anyhow, this is sort of what I'd like to accomplish, so feel free to amend my example or post you preferred methods. Thanks!

+1  A: 

this is improper:

bitmap = new Bitmap(Bitmap(LoaderInfo(event.target).content).bitmapData);

this is proper (notice the lack of new in this example):

bitmap = Bitmap(loader.content);

In terms of the while loop, you are freezing the Flash Player on that line. Flash is single threaded, all of the events that happen after your while clause never happen. it sits there waiting for the loop to break, which will never happen because there is nothing in the loop to break it. That is a limitation of the AVM.

Here's an extended example.

Joel Hooks
I originally had that but I always got:1067: Implicit coercion of a value of type flash.display:DisplayObject to an unrelated type flash.display:BitmapData.I saw the method above in this post: http://stackoverflow.com/questions/644156/as3best-practice-for-getting-image-from-loaderRegardless, this is not the issue I am having trouble with. My problem is that I cannot seem to ever break out of the while loop in my load method.
Scott
I said my problem was that I cannot seem to break out of the while loop in my load method. I should be more general. My problem is that I would like to safely return a Bitmap after the loaded has loaded it. The example you posted doesn't demonstrate this.
Scott
ya, that while loop isn't ever going to break. You have to break it in the loop. You are effectively feezing your app on that line. It also only gives you that Implicit coercion warning when you use the new. loader.content IS a Bitmap. You could say bitmap = loader.content as Bitmap if you prefer.
Joel Hooks
Actually, I still get the warning when I do that. Also, I'm not sure why I'm not not able to break out of the while loop when the listener event function should eventually set hasLoaded to true.
Scott
Oops! Sorry! I should have paid more attention to your example. The lack of new seems to make a difference. However, I'm still not sure this resolves the main issue at hand. Do you know why I cannot break out of the while loop? Can you propose a solution?
Scott
again, the Flash Player **never** moves past that while loop, no events take place, no instructions are processed. You are locking up the application. Infinite while loop. It is busted. Your class needs to dispatch an event when the bitmap is loaded and expose the bitmap property.
Joel Hooks
I think you should consider opening a new question related to the while loop and retrieving asynchronous data from your bitmap loader class.
Joel Hooks
A: 

Hi Scott,

You cannot have this code:

public function load():Bitmap
{
    loader.load(new URLRequest(filePath));

    // this line can *never* work
    while(!hasLoaded);

    return bitmap;
}

You cannot return the bitmap from the load command. You have to exit the function after the request to load and write your code to be asynchronous.

Basically, what you need to write is:

  1. Request the load
  2. Wait for the completeListener callback
  3. Use the Bitmap

So this should read:

public function load():void
{
    loader.load(new URLRequest(filePath));

    // remember you cannot return a Bitmap now.
    // It hasn't loaded yet. You can't wait in here
    // so just return.
}

private function completeListener(event:Event):void
{
    bitmap = new Bitmap(Bitmap(LoaderInfo(event.target).content).bitmapData);

    // HERE the bitmap is *now* available
    // you now need to tell your app that it is available so it can use it.
}
James Fassett