RValentine
RValentine

Reputation: 109

AS3 - Why can't I use stage outside of my root class?

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???

Upvotes: 1

Views: 3313

Answers (2)

James Fassett
James Fassett

Reputation: 41054

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)

Upvotes: 0

back2dos
back2dos

Reputation: 15623

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 ...


greetz

back2dos

Upvotes: 8

Related Questions