views:

489

answers:

2

I have the following two classes:

package 
{
    import flash.display.Sprite;
    import flash.events.Event;

    public class Main extends Sprite
    {

     public function Main():void 
     {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
     }

     private function init(e:Event = null):void 
     { 
      removeEventListener(Event.ADDED_TO_STAGE, init);
      // entry point
      var test:NewClass = new NewClass(); 
     }

    }

}

AND

package  
{
    import flash.display.Sprite;

    public class NewClass extends Sprite
    {

     public function NewClass() 
     {
      trace(stage.width);
     }

    }

}

I get the following error:

TypeError: Error #1009: Cannot access a property or method of a null object reference. at NewClass()[C:\Documents and Settings\Roma\poo\src\NewClass.as:10] at Main/init()[C:\Documents and Settings\Roma\poo\src\Main.as:23] at Main()[C:\Documents and Settings\Roma\poo\src\Main.as:15]

Why???

+2  A: 

yeah, a flash develop user ... :D

uhm, the reason is: the stage is only available to objects, that are on the display list ...

modify your class as follows:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    public class NewClass extends Sprite {
        public function NewClass():void {
                if (stage) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        private function init(e:Event = null):void {       
                removeEventListener(Event.ADDED_TO_STAGE, init);
                trace(stage.width);//you may want to use stage.stageWidth actually
        }
    }
}

and Main::init as follows:

    private function init(e:Event = null):void {       
            removeEventListener(Event.ADDED_TO_STAGE, init);
            var test:NewClass = new NewClass();     
            this.addChild(test);
    }

oh, and you can change your Coding Style Type from BraceAfterLine to BraceOnLine in Tools > Program Settings > FlashDevelop > Indenting, just in case you are inclined ... ;)


edit: if you want to access the stage, within the scope of a DisplayObject, you need to be sure, the stage is available to it ... if you want to access the stage as soon as possible, then you will need the trick provided ... but if you access the stage within a click handler for example, this automatically implies the DisplayObject is on the display list ... it couldn't be clicked otherwise ...

a little note though: i don't think, it's particularly clever to access the stage from everywhere ... when it comes to display, your app hierarchy should follow the display list hierarchy, i.e. access goes from the root down the branches, and not the other way round ... this is important to achieve reusability ...


back2dos
So does that mean if I import a library, I will need to add the if (stage)... lines of code to every class that uses stage?
RValentine
If the library you're importing references "stage", then it probably won't function unless it's been added to the stage. Rather than editing it, the solution is probably to make sure it's added to the stage when it needs to be.
fenomas
A: 

As back2dos correctly says, only elements that are on the display list have a valid reference to the stage. As the instance of NewClass is merely a temporary variable in the init method of your Main instance and you have yet to addChild to put it on the display list the value of it's stage property will be null. Note: only children of parents which are also on the display list will obtain a valid reference to the stage.

If you need a reference to the stage in a class that will not be added to the display list then you will need to pass the stage into an instance of that class. Unlike AS2 there is no globally accessible reference to the stage (i.e. _root and _level0 are deprecated)

James Fassett