Can I access Stage from an AS3 Class with no DisplayObject?

Social Share Toolbar

I’m working on a project that requires creating and adding a Movie Clip to the Stage from a class file. Seemed like an easy task, however, referring to the Stage from my class turned out to be trickier than I thought.

I know that, although you can’t refer to Stage directly, it is a property of every DisplayObject named ‘stage’ (lower case ‘s’). For example, if my class extends Sprite, I can get the Stage width by referring to “stage.width”.

The problem arises when a class does not extend a DisplayObject and a DisplayObject is not passed to your class. The project I’m working on fell into this category. The purpose of my class is simply to create and manage instances of another class. The problem I ran into was that I could not refer to the Stage because my class had no reference to a DisplayObject.

I ended up working around the problem by passing a DisplayObject instance, but out of curiosity, I’d like to know if there is any way around this issue. Is there a way to refer to the Stage from a class file that has no DisplayObject instance?

-rG

14 thoughts on “Can I access Stage from an AS3 Class with no DisplayObject?

  1. The easiest way is to set up a class with static references to the stage, that you then extend for all your document classes:


    package
    {
    import flash.display.MovieClip;
    import flash.display.Stage;
    public class GlobalStage extends MovieClip
    {
    public static var STAGE:Stage;
    public static var ROOT:MovieClip;

    public function GlobalStage()
    {
    STAGE = this.stage;
    ROOT = this.root;
    }
    }
    }

    Tom-

  2. One thing to watch out for when using the method suggested by SFBTom: If you are dealing with the main SWF, this works because the Flash player wires up the “stage” reference before the constructor is called (but still triggers the ADDED_TO_STAGE event afterwards). However, if your SWF is a secondary load, you must wait for the ADDED_TO_STAGE event because stage will be null when your constructor is called.

    You can always architect it so that your secondary SWF depends on the initial SWF, but you will have problems if you want to test it independently because your code will behave differently.

    My general solution is to create a one-time ADDED_TO_STAGE event handler to the document class that does the work I would generally put into the constructor. The actual constructor just wires up the event handler and holds off adding any of its children. This way, we know that stage is available before any other objects have been created, even when the SWF is a secondary load. It won’t work if you are using CS3 and have items on the stage that might depend on it, but it will work if you keep your root timeline clean and do the initial setup in ActionScript.

  3. Use my Global class. It allows you to have global storage without overriding or extending main classes.

    Download: http://www.uza.lt/codex/as3-global-object/

    Usage
    ———-
    Call this code from your main application class:

    private var global:Global = Global.init();
    ...
    global.stage = this.stage;

    And this code from any other class:

    private var global:Global = Global.init();
    ...
    trace(global.stage);

  4. Thanks for all the suggestions! It’s interesting to see the different approaches. I’m a little surprised that there isn’t an ‘out of the box’ solution but it’s good to know that there are work-arounds available.

    @Paulius: Congratulations on the MTV Greece partnership!

    Glenn

  5. Thank you for this answer. I have been looking for a long time for this. It seems so obvious now. That is usually how it is.

    • me too. I used to just add the values as global vars but that was always a pain to update. This is how we learn!

  6. Getting around the old “_root” problem had me confused for a bit when I upgraded from AS2 to AS3. It could be useful to mention here that you can access the document class from another class by referencing the document class in your other classes, ie when inside another class, and you want to access a PUBLIC variable within the document class called “bob” you can call it by…

    MovieClip(root).bob;

  7. James – will you have my babies? Why oh why do Adobe make migration so complicated? Now I can go back to the things I could do in AS1.0 by popping code on objects (admittedly now as classes) and make that crazy shmup I’ve always wanted to without trying to call 50+ objects individually. Might not be tidy, but it works. Why dont Adobe just say in big letters, ‘when you used to say _root from an object, now say MovieClip(root)’? Damn them. And damn them for the transcoding bug in Encore as well. But bless them for giving me a career (and many headaches)

    Thanks,

    Karl

  8. what i did was give the constructor an argument

    function ImageScroller(theWidth:Number):void {

    theWidth is then passed when an instance of the class is created
    like so…

    var img:ImageScroller = new ImageScroller(stage.stageWidth);
    addChild(img);
    trace(stage.width);

    so far it works fine, at least for my purposes.

  9. Simply broadcast an event that is caught by something with a stage reference. I’ve read far to much code where people pass the stage around. USE EVENTS!

    • Events are great, however, if the class included ‘something with a stage reference’, then a reference to the stage wouldn’t be needed in the first place.