views:

30

answers:

2

I'm an experienced AS developer, but this is something very basic about flex that I can't figure out. In the class below, I'm not sure why the function imageLoaded would not be executed when the image loads a url. Is there a race condition happening here? The application is completely loaded by the time this object is created and setPicture is called. How can I get the Event.COMPLETE event to fire properly in this case?

The line and Log.info functions are conveniences for me, and they definitely work.

Here's my MXML definition:

<?xml version="1.0" encoding="utf-8"?>
<photo:PhotoClass xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:photo="com.xxx.widgets.photo.*">
    <mx:Image id="image"/>
</photo:PhotoClass>

Here's my actionscript:

public class PhotoClass extends Box {

    public var image : Image;

    public function PhotoClass() {
        image = new Image();
        image.addEventListener(Event.COMPLETE, imageLoaded);
    }

    private function line(txt : *) : void {
        Log.info(txt, "PhotoClass");
    }

    public function setPicture(url : String) : void {
        line("setPicture: " + url);         
        image.source = url;         
    } 

    public function imageLoaded(event : Event) : void {
        line("image loaded");
    }
}
+1  A: 

I figured it out...

eventListeners won't register unless the sprite is attached to the application. The eventListener in this case was being added in the constructor, before the sprite was added to its parent class. I moved image.addEventListener to setPicture and it worked.

Lava
Good job; Be sure to mark your own answer as the correct one.
www.Flextras.com
@www I believe the issue is something else. Can you please check my answer and confirm - I don't have access to a compiler right now.
Amarghosh
+3  A: 

eventListeners won't register unless the sprite is attached to the application.

Can you give a reference? Because I believe the issue is something else.

When you declare an mxml file with PhotoClass as its root tag, you're extending the PhotoClass. The <mx:Image> tag in the mxml defines a public variable of type Image in the mxml class; and you already have a public var image:Image; in the super class. This will create a conflict - I'd expect a compile time error.

My guess is that since constructor is called first, it assigns an Image object to the public variable image. When the mxml is executed and the children are created, it assigns a new Image object to the public variable image (instead of correctly throwing an error). Now, the event listener was added to the Image instance created in the constructor, but by the time you set image.source in setProperty, it is a different object altogether. That is why it works when you move the event listener to setPicture - there you're assigning it to the new object.

Change the id of the mxml Image tag to something else and it will work even if the event listener was added from the constructor. Change the name of public var image to something else and you'll get a compile time error in PhotoClass.

Btw, what does the Image tag in the mxml do - is that for showing a different image? In that case you must change its id.

<!-- MyCanvas.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"&gt;
  <mx:Label id="lbl"/>
</mx:Canvas>

<!-- the main application class -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*" 
   creationComplete="onCreate()" layout="vertical">
  <local:MyCanvas id="canvas1"/>
  <mx:Script>
    <![CDATA[
      public var canvas2:MyCanvas;
      public function onCreate():void
      {
        this.canvas1.lbl.text = "MyCanvas_1";
        canvas2 = new MyCanvas();
        this.addChild(canvas2);
        canvas2.addEventListener(FlexEvent.CREATION_COMPLETE, onCanvas2Created);
      }
      public function onCanvas2Created(e:FlexEvent):void
      {
        this.canvas2.lbl.text = "MyCanvas_2";
      }
    ]]>
  </mx:Script>
</mx:Application>
Amarghosh
+1 because that makes a lot of sense. When I saw the question already answered; I didn't take a deep look. UInfortunately, I'm not at the compiler right now either.
www.Flextras.com
"The <mx:Image> tag in the mxml defines a public variable of type Image in the mxml class; and you already have a public var image:Image; in the super class. This will create a conflict - I'd expect a compile time error."Flex requires you to declare this object again (as public) in actionscript if you want to be able to do any scripting in a separate class. So, no compile error. As a matter of fact, it would throw an error you didn't.
Lava
@Lava *Flex requires you to declare this object again (as public) in actionscript if you want to be able to do any scripting in a separate class* Wrong. Every mxml component creates a public variable in the class whose name is its id attribute. You can access the component from a separate class using its id attribute
Amarghosh
@Lava check my update to see what I am talking about
Amarghosh