ActionScript - глобальные пользовательские события? - PullRequest
2 голосов
/ 28 января 2011

До сих пор мне приходилось обрабатывать свои собственные пользовательские события, добавляя прослушиватель событий к объекту, который отправлял пользовательское событие.хотя этот метод обработки событий работает очень хорошо, я пришел к тому, что мне бы хотелось, чтобы мои пользовательские события были глобально доступны, когда прослушивающий объект не обязательно должен быть тем же объектом, который отправляет событие.

в этом примере мой основной контроллер создает и добавляет в список отображения 2 класса спрайтов: Квадрат и Треугольник .4-й и последний класс - это пользовательское событие с именем ColorChangeEvent .

Я пытаюсь отправить новый ColorChangeEvent из класса Square, который использует таймер для отправкиновый случайный цвет раз в секунду, в то время как треугольник будет прослушивать отправленное событие и изменяет цвет заливки на цвет, который был отправлен квадратом.

Controller.as:

package
{
import flash.display.Sprite;

public class Controller extends Sprite
    {
    public function Controller()
        {
        var sq:Square = new Square();
        sq.x = sq.y = 100;

        var tr:Triangle = new Triangle();
        tr.x = tr.y = 250;

        addChild(sq);
        addChild(tr);
        }
    }
}

Square.as:

package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;

    public class Square extends Sprite
        {
        public function Square()
            {
            graphics.beginFill(0x999999);
            graphics.drawRect(0, 0, 100, 100);
            graphics.endFill();

            var myTimer:Timer = new Timer(1000);
            myTimer.addEventListener(TimerEvent.TIMER, dispatchNewColor);
            myTimer.start();
            }

        private function dispatchNewColor(evt:TimerEvent):void
            {
            var randomColor:Number = Math.random() * 0xFFFFFF;
            trace("Square Class Dispatched: " + randomColor);

            dispatchEvent(new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor));
            }
        }
    }

Triangle.as:

package
{
import flash.display.Sprite;
import flash.geom.ColorTransform;

public class Triangle extends Sprite
    {
    public function Triangle()
        {
        graphics.beginFill(0x999999);
        graphics.moveTo(0, 0);
        graphics.lineTo(100, 50);
        graphics.lineTo(-50, 150);
        graphics.endFill();

        addEventListener(ColorChangeEvent.CHANGE, changeColor);
        }

    private function changeColor(evt:ColorChangeEvent):void
        {
        var ct:ColorTransform = new ColorTransform;
        ct.color = evt.color;

        transform.colorTransform = ct;

        trace("Triangle Class Received: " + evt.color);
        }
    }
}

ColorChangeEvent.as:

package
{
import flash.events.Event;

public class ColorChangeEvent extends Event
    {
    public static const CHANGE:String = "change";
    public var color:Number;

    public function ColorChangeEvent(type:String, color:Number) 
        {
        super(type);
        this.color = color;
        }

    override public function clone():Event
        {
        return new ColorChangeEvent(type, color);
        }
    }
}

Излишне говорить, что это не работает.

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

не всегда легко получить доступ и передать значение в класс, откудапользовательское событие отправляется, поэтому я смотрюng для фактического глобального решения для обработки пользовательских событий.

Ответы [ 3 ]

4 голосов
/ 28 января 2011

Я использую этот класс уже некоторое время.Чтобы использовать его, вы должны сделать это в квадрате:

data.EventManager.instance.publish("someName", randomColor);

и затем в своем треугольнике:

data.EventManager.instance.subscribe("someName", handleColorChange);

private function handleColorChange(color:Number):void {
    // implementation here
}

Вы можете даже передать ColorChangeEvent вместо только цвета.

data.EventManager.instance.publish(ColorChangeEvent.CHANGE, new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor);

А потом

data.EventManager.instance.subscribe(ColorChangeEvent.CHANGE, handleColorChange);

private function handleColorChange(colorChangeEvent:ColorChangeEvent):void {
    // implement here
}

Я удалил много кода, характерного для моих проектов, поэтому я не на 100% пригоден для использования в точности как есть.Но вы должны иметь возможность изменить его, чтобы он работал правильно.Если нет, дайте мне знать, и я могу попытаться решить это с вами.

Этот класс обрабатывает дополнительные вещи, в которые я не буду вдаваться, хотя вы свободны исследовать.Имейте в виду, однако, что все, что подписывается на уведомление о событии, имеет сильную ссылку EventManager.Это означает, что если вы хотите уничтожить что-то для сборки мусора, вам нужно вызвать EventManager.instance.cancel(ColorChangeEvent.CHANGE, handleColorChange), прежде чем можно будет собирать экземпляры треугольника.

package data {
    import flash.utils.*;

    public class EventManager extends Object {
        private var _subscribers:Dictionary;
        private var _calls:Dictionary;
        private var _feeds:Dictionary;
        private var _requests:Dictionary;
        private var _notify:Dictionary;
        private var _services:Dictionary;
        private static var __instance:EventManager;

        public function EventManager() {
            if (__instance) {
                trace("EventManager is a Singleton class which should only be accessed via getInstance()");
            }
            _feeds = new Dictionary(true);
            _subscribers = new Dictionary(true);
            _requests = new Dictionary(true);
            _services = new Dictionary(true);
            _notify = new Dictionary(true);
        }

        public function getFeedData($name:String) {
            if (_feeds[$name]) {
                return _feeds[$name];
            }
            return undefined;
        }


        public function unpublish($name:String) {
            var _post:* = _feeds[$name];
            delete _feeds[$name];
            return _post;
        }

        public function cancel($name:String, $subscriberFunc:Function, ...args): void {
            var _cnt:Number;
            var _subscriberArray:Array;
            if (_subscribers[$name]) {
                for (_cnt = 0; _cnt < _subscribers[$name].length; _cnt++) {
                    if (_subscribers[$name][_cnt] == $subscriberFunc) {
                        _subscribers[$name].splice(_cnt, 1);
                    }
                }
            }

            if (_requests[$name]) {
                _subscriberArray = _requests[$name];
                _cnt = _subscriberArray.length;

                while (_cnt > 0) {
                    if (_subscriberArray[_cnt] == $subscriberFunc) {
                        _subscriberArray.splice(_cnt, 1);
                    }
                    _cnt--;
                }
            }
        }

        public function subscribe($name:String, $subscriber:Function, ...args): void {
            var _funcArray:Array;
            var _func:Function;


            if (_feeds[$name]) {
                $subscriber(_feeds[$name]);
            }

            if (! _subscribers[$name]) {
                _subscribers[$name] = new Array();
            }
            _subscribers[$name].push($subscriber);

            if (_notify[$name]) {
                _funcArray = _notify[$name];

                for each (_func in _funcArray) {
                    _func();
                }
                delete _notify[$name];
            }
        }

        public function request($name:String, $feedFunction:Function): void {
            var _requestArray:Array;
            var _request:Function;

            if (! _feeds[$name]) {
                if (! _requests[$name]) {
                    _requests[$name] = new Array();
                }
                _requests[$name].push($feedFunction);
            } else {
                $feedFunction(_feeds[$name]);
            }

            if (_notify[$name]) {
                _requestArray = _notify[$name];

                for each (_request in _requestArray) {
                    _request();
                }
                delete _notify[$name];
            }
        }

        public function publish($name:String, $data:*, $args:Object = null): void {
            var _subscriberArray:Array;
            var _func:Function;
            var cnt:Number = 0;
            _feeds[$name] = $data;

            if (_subscribers[$name] != undefined) {
                _subscriberArray = _subscribers[$name].slice();
                _cnt = 0;

                while (_cnt < _subscriberArray.length) {
                    _func = _subscriberArray[_cnt] as Function;

                    if ($args) {
                        _func($data, $args);
                    }else {
                        _func($data);
                    }
                    _cnt++;
                }
            }

            if (_requests[$name]) {
                _subscriberArray = _requests[$name].slice();
                delete _requests[$name];
                _cnt = 0;

                while (_cnt < _subscriberArray.length) {
                    if (_subscriberArray[_cnt] != null) {
                        _subscriberArray[_cnt]($data);
                    }
                    _cnt++;
                }
            }
        }

        public function notify($name:String, $subscriber:Function): void {
            if (_requests[$name] || _subscribers[$name]) {
                $subscriber();
            }else {
                if (! _notify[$name]) {
                    _notify[$name] = new Array();
                }
                _notify[$name].push($subscriber);
            }
        }


        public static function getInstance(): EventManager {
            if (! __instance) {
                __instance = new EventManager();
            }
            return __instance;
        }

        public static function get instance(): EventManager {
            return getInstance();
        }
    }
}
1 голос
/ 02 января 2015

Я получил это на работу, создав синглтон: EventDispatchSingleton, что extends EventDispatcher.В основном это пустой синглтон, который предоставляет методы dispatchEvent и add / removeEventListener (они автоматически предоставляются расширением EventDispatcher).

Везде, где я хочу отправить событие, я импортирую EventDispatchSingleton и затем вызываю EventDispatchSingleton.instance.dispatchEvent(<someEvent>);.

Затем, куда бы я ни захотел прослушать это событие, я просто импортирую EventDispatchSingleton и вызываю EventDispatchSingleton.instance.addEventListener(eventName, callback);

0 голосов
/ 28 января 2011

Вы должны посмотреть на всплывающие события, в частности, я думаю, что вы найдете фазу захвата распространения события полезной.Прочитайте Распространение событий от Adobe LiveDocs .Это в документах Flex, но это о событиях AS3.

Также У Senocular есть хороший пост о всплывающих событиях Flash .

...