AS3引用库符号的自定义类中的自定义属性

时间:2012-09-21 19:25:08

标签: actionscript-3 oop

所以我已经通过SO进行了大量的搜索,但却找不到这个问题的答案。我的符号库中有一个动画片段,它是为actionscript导出的,我为它编写了一个自定义类。除了在我将movieclip添加到舞台后尝试访问自定义私有属性时,它的效果非常好。下面是一个例子:

package {

    public class MyMovieClip extends MovieClip {

        private var _isEnabled:Boolean = false;

        public function MyMovieClip():void {

            trace(this);
        }

        public function set isEnabled( b:Boolean ):void {

            _isEnabled = b;
        }

        public function get isEnabled():Boolean {

            return _isEnabled;
        }
    }
}

然后我有另一个类,我将一个movieclip的实例添加到循环中的舞台:

package {

    public class MyOtherClass extends MovieClip {

        public var myMC:MyMovieClip;
        public var docClass:*;

        public function MyOtherClass( docRef:* ):void { // passing in a reference to the DocumentClass so I can access the stage
            docClass = docRef;
            init();
        }

        public function init():void {

            for(var i:int=0; i<6; i++) {

                var myMC:MyMovieClip = new MyMovieClip; // instantiate the movieclip which is exported for actionscript and has a custom class 
                //set a few native properties
                myMC.name = "myMC" + i; //setting the name so I can reference this movieclip after it's been added to stage
                myMC.y = myMC.height * i + 20;
                myMC.x = 20;
                myMC.alpha = .7;
            }

            dispatchEvent(new Event(MyOtherClass.MOVIECLIPS_ADDED)); // just to be safe, let's dispatch a custom event when all movieclips have been added
        }

        public function traceEnabled():void {

            trace(docClass.stage.getChildByName("myMC1").isEnabled); // this throws: 1119: Access of possibly undefined property isEnabled through a reference with static type flash.display:DisplayObject

        }
    }
}

最后我在我的文档类中实例化了MyOtherClass:

package {

    public class DocumentClass extends MovieClip {

        public var myOtherClass:MyOtherClass;

        public function DocumentClass():void {

            addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
        }

        public function onAddedToStage(e:Event):void {

            myOtherClass = new MyOtherClass(); // upon instantiation, init is called in MyOtherClass and all of my movieclips are added to the sage
        }
    }
}

是什么给出的?为什么我不能在将它添加到舞台后访问MyMovieClip属性isEnabled?还有另外一种方法吗? (提前感谢您的帮助)

1 个答案:

答案 0 :(得分:0)

DisplayObjectContainer内部的所有子项都被引用为DisplayObject,因此当您使用getChildByName时,它会返回一个DisplayObject。

要在不导致编译时错误的情况下访问自定义属性,您需要将getChildByName的结果强制转换为自定义属性的类。请参阅下面的代码。

然而,这不是你唯一的问题(虽然这是错误的原因,一旦你纠正,你也会得到运行时错误。)

在你的创建循环中,你没有将myMC添加到显示列表中,因此调用stage.getChildByName()将返回null,因为你的剪辑不在舞台上。

您也没有将myOtherClass添加到已发布代码中的显示列表中。

此外,实际上不需要存储对文档类的引用。只需在MyOtherClass中添加addedToStage侦听器,并将处理程序设置为init。

这里有一些更新的代码 对于MyOtherClass

    public function MyOtherClass():void { 
        if(stage){
            init(); //if stage is ready, call init, if not wait for the added to stage event
        }else{
            addEventListener(Event.ADDED_TO_STAGE,init);
        }
    }

    public function init(e:Event = null):void {
        removeEventListener(Event.ADDED_TO_STAGE,init);

        for(var i:int=0; i<6; i++) {

            var myMC:MyMovieClip = new MyMovieClip;
            myMC.name = "myMC" + i; //setting the name so I can reference this movieclip after it's been added to stage
            myMC.y = myMC.height * i + 20;
            myMC.x = 20;
            myMC.alpha = .7;

            addChild(myMC); //!!!! add to the displayList
        }

        dispatchEvent(new Event(MyOtherClass.MOVIECLIPS_ADDED)); // just to be safe, let's dispatch a custom event when all movieclips have been added
    }

    public function traceEnabled():void {
        var myMC:MyMovieClip = this.getChildByName("myMC1") as MyMovieClip; //!!! cast it as MyMovieClip so you have access to all the properties/methods in that class
        if(myMC){  //myMC will be null if the cast failed
            trace(myMC.isEnabled); 
        }
    }

    /*
       getChildByName is slow and cumbersome. Most people generally only use it for accessing things put on the timeline in the Flash IDE.  Using events is a much better way of accessing your items. If traceEnabled was caused by a mouse event attached to myMC, then this would be a much better implementation:
    */
    public function betterTraceEnabled(e:Event):void {
        var myMC:MyMovieClip = e.currentTarget as MyMovieClip;
        if(myMC){
            trace(myMC.isEnabled);
        }
    }

和你的文件类:

public class DocumentClass extends MovieClip {

    public var myOtherClass:MyOtherClass;

    public function DocumentClass():void {

        if(stage){
            onAddedToStage(null); //most of the time stage is already populated in the constructor of your document class
        }else{
            addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
        }
    }

    public function onAddedToStage(e:Event):void {

        myOtherClass = new MyOtherClass(); // upon instantiation, init is called in MyOtherClass and all of my movieclips are added to the sage
        addChild(myOtherClass); //add it to the displayList
    }
}