Flash CS5 ссылается на экранный объект в конструкторе класса без документов - PullRequest
1 голос
/ 29 июля 2011

Узнав об этом превосходном методе доступа к объекту, помещенному на сцену в Flash CS5, в классе, отличном от класса документа (найден в этой теме ), я наткнулся на точку преткновения.Я использую

this.stage.getChildAt(0).greenLight1.visible=false;

, чтобы превратить символ с именем экземпляра greenLight1, невидимым при доступе к greenLight1 (имя экземпляра, указанное в моем .fla для растрового изображения).Это прекрасно работает там, где я использовал его, который находится в подфункции нескольких разных классов.Проблема, с которой я сталкиваюсь, заключается в том, что вы не можете использовать это в конструкторе этих недокументированных классов или в любой функции, вызываемой непосредственно конструктором.Если я пытаюсь это сделать, я получаю следующее сообщение об ошибке «Ошибка № 1009: не удается получить доступ к свойству или методу пустой ссылки на объект».

Так что я понимаю, что не получаю доступ к этому правильно, и начинаю игратьс фразой.Когда я переключаю его на

this.getChildAt(0).greenLight1.visible=false;

, я получаю другую ошибку «1119: Доступ к возможно неопределенному свойству greenLight1 через ссылку со статическим типом flash.display: DisplayObject.»Так что я явно чего-то здесь упускаю.

Теперь я попробовал другую тактику, которую я нашел в этой теме , которую я также упомянул в приведенной выше ссылке на тему, которую я настроил.И благодаря комментарию Аллана в моей другой ветке, я фактически заставил этот метод работать.Однако, когда я пытаюсь поместить эту ссылку в класс конструктора любого другого класса, не относящегося к документу, я фактически получаю ту же ошибку «Ошибка № 1009: не удается получить доступ к свойству или методу пустой ссылки на объект».Но это прекрасно работает, если я использую его в подфункции.Похоже, та же проблема.

Мой проект состоит из файла Game.fla, в котором содержатся различные растровые символы и несколько кнопок, которые я поместил в свою библиотеку и перетащил на сцену (и я дал им всеуникальные имена экземпляров).Я настроил свой класс документов Game.as, и внутри него я могу получить доступ ко всем этим элементам, просто используя их имя экземпляра.Теперь в моем подклассе под названием Player.as я настроил функцию lightsOut (), которая выключает свет, используя переключатель / чехол.Именно там я использую "this.stage.getChildAt (0) .greenLight1.visible = false;"и это работает отлично.Здесь я также установил другую тактику, о которой упоминал выше, и попробовал «Game.GL1.visible = false;»и это отлично сработало.Но затем в моем подклассе под названием Controller.as, где у меня есть все мои обработчики мыши и клавиатуры, я попытался настроить прослушиватель событий для одной из моих кнопок этапа.Поэтому я поместил его в функцию конструктора Controller, где все мои другие прослушиватели событий настроены и уже работают (они используют «stage.addeventlistener ...»), и именно здесь я начал видеть ошибки.Так что я решил попытаться отключить greenLight1, так как я уже знал, что код работает, и пробовал только строку «this.stage.getChildAt ....» и только строку «Game.GL1 ...»смотреть их вызывают ошибки, которые я упоминал выше.Поэтому я вернулся к своему классу Player.as и попробовал их в классе конструктора Player, и снова получил те же ошибки, даже если я использую ту же строку ниже в классе Player.as.Обратите внимание, что я прошел стадию и для Controller, и для Player и прекрасно использовал ее в обоих случаях.Я также попытался настроить вызов другой функции в конструкторе с именем Init ();и получил ту же ошибку при попытке получить доступ к greenLight1, но он все еще работал в lightsOut ().Также не уверен, имеет ли это значение, но все классы также расширяют MovieClip.Я не знаю, поможет ли это, но вот начало класса Player вместе с функцией lightsOut. Я удалил оставшуюся часть кода, поскольку она не связана:

package {
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.DisplayObject;

public class Player extends MovieClip {
    private var _stage:Object;
    private var _lights:uint;

    public function Player(stage:Object):void {
        this._stage = stage;
        this._stage.getChildAt(0).greenLight1.visible=false; //errors
        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }
    private function lightsOut():void {
        switch(_lights) {
            case 1:
            this._stage.getChildAt(0).greenLight1.visible=false;//works
            break;
            case 2:
            this._stage.getChildAt(0).greenLight2.visible=false;//works
            break;
            case 3:
            this._stage.getChildAt(1).greenLight3.visible=false;//works
            break;
        }
    }

Чего мне не хватаетздесь?

РЕДАКТИРОВАТЬ: ОК, вот класс документа (по крайней мере, что важно для контроллера и проигрывателя):

public class Game extends MovieClip {
    private var _player:Player = new Player(stage);
    private var _controller:Controller = new Controller(_player, stage);

    public function Game():void {
        addChild(_player);
        addEventListener(Event.ADDED_TO_STAGE, added);

Вот важная часть класса Controller, и я добавил комментарий к тому, что терпит неудачу (реальная причина, по которой я начал этот пост в первую очередь):

public class Controller extends MovieClip {
private var _stage:Stage;
private var _model:Object;

public function Controller(model:Object, stage:Stage):void {
    this._model = model;
    this._stage = stage;

    _stage.addEventListener(KeyboardEvent.KEY_DOWN, processKeyDown);
    _stage.addEventListener(KeyboardEvent.KEY_UP, processKeyUp);
    _stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    this._stage.getChildAt(0).fireButton.addEventListener(MouseEvent.CLICK, onClick); //this is what isn't working
    this._stage.getChildAt(1).greenLight1.visible=false; //added this for testing

Эта последняя строка, которую я только добавил, чтобы увидеть, смогу ли я сделать greenLight1 невидимым, как когда я вызываю его в функции lightsOut (), которую я отметил в Player.as. Но это НЕ работает, когда размещено здесь в конструкторе. ПОМОГИТЕ!!!! лол

Ответы [ 3 ]

1 голос
/ 29 июля 2011

Проблема, с которой вы столкнулись, заключается в том, что вы создаете экземпляр класса контроллера до того, как у вас есть объект stage, который нужно передать ему. Вы должны подождать, пока не наступит событие ADDED_TO_STAGE, чтобы создать экземпляр всего остального:

public class Game extends MovieClip {
    private var _player:Player;
    private var _controller:Controller;

    public function Game():void
    {
        addEventListener(Event.ADDED_TO_STAGE, added);
    }
    private function added(evt:Event):void
    {
        removeEventListener(Event.ADDED_TO_STAGE, added);
        _player = new Player(stage);
        _controller = new Controller(_player,stage);
        addChild(_player);
    }
}

Есть лучший способ

Вам не нужно проходить сцену через своего игрока и диспетчера. Если вы просто передадите ссылку на this, вы передадите ссылку на класс документа. Это более эффективная практика, поскольку она готовит вас к более сложным программным подходам, таким как шаблоны проектирования .

То есть у вас есть класс документа:

public class Game extends MovieClip {
    private var _player:Player;
    private var _controller:Controller;

    public function Game():void
    {
        addEventListener(Event.ADDED_TO_STAGE, added);
    }
    private function added(evt:Event):void
    {
        removeEventListener(Event.ADDED_TO_STAGE, added);
        _player = new Player(this);
        _controller = new Controller(_player,this);
        addChild(_player);
    }
}

и в вашем классе игрока:

public class Player extends MovieClip {
    private var docRef:Game;
    private var _lights:uint;

    public function Player($docRef:Game):void {
        this.docRef = $docRef;
        docRef.greenLight1.visible=false; //no longer needs to wait for player to be on the stage
    }
}

Преимущество очевидно, поскольку вы знаете, что ваш класс документов находится на сцене, Player не должен находиться на сцене, прежде чем он сможет взаимодействовать с ним. Не нужно когда-либо быть на сцене. Если вам нужен stage, скажем, для добавления слушателей, как вы делаете это в Контроллере, вы можете использовать свойство stage документов:

docRef.stage.addEventListener ...
1 голос
/ 29 июля 2011

Тот факт, что вы не можете получить доступ к экземплярам на сцене в конструкторе класса, но можете сделать это в другой функции класса (которую вы вызываете позже, я полагаю) заставляет меня думать, что сценарий недоступен вашему конструктору, когда онбудучи призванным

Убедитесь, что ваш класс документа Game.as настроен следующим образом, хотя, вероятно, это так, поскольку вы следовали моему методу:

public function Game() {
    addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
    //DO NOT CREATE CLASS INSTANCES IN HERE
}

private function init(e:Event):void{
    //In here is where we create instances of classes
}

Кроме того, установите тип данных рабочей области равнымStage вместо Object в параметре конструктора вашего класса Player для хорошей практики кодирования.

0 голосов
/ 29 июля 2011

stage - это свойство DisplayObject, доступное / определенное только после того, как оно было добавлено к DisplayList (то есть - добавлено к чему-либо через addChild())

Вам не повезет получить доступ к stage из конструктора класса, если это не класс документа.

Как уже упоминалось, вы можете переместить содержимое вашего конструктора в пользовательскую функцию, которая вызывается после запуска Event.ADDED_TO_STAGE.

Например, вот демонстрационный класс:

public class Thing extends DisplayObject
{
    /**
     * Constructor
     */
    public function Thing()
    {
        // Add listener
        addEventListener(Event.ADDED_TO_STAGE, _added);
    }

    /**
     * Called once this has been added to the display list
     * @param e Event.ADDED_TO_STAGE
     */
    private function _added(e:Event):void
    {
        // Discard listener
        removeEventListener(Event.ADDED_TO_STAGE, _added);

        // My initial code
        trace(stage + " is accessible");
    }
}

Который мы затем создаем экземпляр:

var thing:Thing = new Thing(); // nothing happens

А затем добавьте в сцену / текущий контейнер:

addChild(thing); // output: [Object Stage] is accessible

Что касается доступа к greenLight1, это должно быть легко достигнуто с помощью одного из следующих действий:

stage.greenLight1;
stage["greenLight1"];

Также вы можете заменить:

public function Player(stage:Object):void

С:

public function Player(stage:Stage):void
...