ActionScript:如何实例化将自身添加到舞台的Sprite子类?

时间:2010-12-31 20:25:42

标签: flex actionscript

我在Sprite周围创建了一个名为ClickableCircle的包装器,用于在实例化时将自身添加到显示列表中。这是一个玩具版本:

public class ClickableCircle extends Sprite {
    protected var circle:Shape;
    protected var myName:String;

    public function ClickableCircle(name:String, x:uint, y:uint) {
        super();
        circle:Shape = new Shape();
        circle.graphics.beginFill(0x00ACDC, 1);
        circle.graphics.drawCircle(0, 0, 12);
        this.myName = name;
        this.x = x;
        this.y = y;
        this.addChild(circle);
        this.addEventListener(MouseEvent.CLICK, reportClickedID);
        // Here's the problematic line: can't add itself to display list
        // Error #1009: Cannot access a property or method of a null object reference.                                  
        stage.addChild(this);   
        trace("Created " + name + " at " + String(x) + ", " + String(y));
    } 

    private function reportClickedID(e:MouseEvent):void {
        trace("You just clicked on " + this.myName);
    }
}

问题在于,当从主应用程序实例化ClickableCircle时,它会在尝试将自身添加到舞台时崩溃,bc stage为null。另一方面,如果addChild()从ClickableCircle构造函数中注释掉,并且实例化的cs被添加到主应用程序级别的显示列表中,那么一切正常:

public class GreetingApp extends Sprite {
    public function GreetingApp() {
        var cs:ClickableCircle = new ClickableCircle("joe", 100, 200);

        // If the child is added here, everything works.
        stage.addChild(cs);
    }
}

由于GreetingApp和ClickableCircle都扩展了Sprite,我认为该阶段将在两个地方实例化并可访问。我是ActionScript / Flex的新手,所以我确定我做的事情很愚蠢。谁能告诉我它是什么?

2 个答案:

答案 0 :(得分:2)

你是对的,舞台将为空。原因是因为DisplayObjects只有在添加到显示列表后才会对stage进行隐式引用。在你的情况下,这会产生一些捕获22。

至少有几种方法可以解决这个问题。


选项1:在构造函数中传递对舞台的引用。像

这样的东西
var cs:ClickableCircle = new ClickableCircle("joe", 100, 200, stage);

现在,在ClickableCircle实例中,您可以访问舞台。我通常会像这样使用它

public function ClickableCircle(name:String, x:uint, y:uint, target:*) {
    ...
    target.addChild(this);
}

选项2.您可以使用静态变量来引用主应用程序类中的舞台。或者,同样地,您可以使用在创建ClickableCircle之前实例化的单例,并将对该阶段的引用传递给单例。然后你可以从任何地方访问它。

public static var STAGE:DisplayObjectContainer;

然后,假设您的类名为Main,您可以在ClickableCircle类中执行此操作:

Main.STAGE.addChild(this);

如果这没有意义,或者您需要更多帮助,请告诉我。

答案 1 :(得分:1)

实际上,一个有用的实用程序是一种StageManager,它是从Main Application Sprite / MovieClip / DisplayObject设置的。您可以键入Stage的访问者,因为这是更合适的类类型。

private var _stage:Stage;

public static function get stage() : Stage
{
    if( stage == null ) throw new Error( "You must set the stage in your root before trying to access it." );    
    return stage;
}

public static function set stage( value:Stage )
{
    _stage = value;
}

这是一个合理的单例,因为每个应用程序中只有一个Stage实例。