Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как передать параметр в фунцию, вызванную addEventListener'ом? (http://www.flasher.ru/forum/showthread.php?t=138562)

gait 10.04.2010 23:29

Как передать параметр в фунцию, вызванную addEventListener'ом?
 
Нужно, чтобы в каждом фрейме трейсился заданный элемент массива. Как передать в функцию traceNumEnterFrame() параметр?
Код AS3:

package {
        import flash.display.MovieClip;
        import flash.events.*;
        public class arrayCheck extends MovieClip {
                var myArray:Array;                       
                public function arrayCheck() {
                        myArray = new Array(1,2,3,4,5,6,7,8,9,10);                       
                        var myVar:uint = 4;                       
                        addEventListener(Event.ENTER_FRAME, traceNumEnterFrame);
                }
                public function traceNumEnterFrame(event:Event) {
                        trace(myArray[myVar]);//1120: Access of undefined property myVar.
                }
        }
}


etc 10.04.2010 23:32

Ну сделайте myVar полем класса.

mikhailk 10.04.2010 23:37

Код AS3:

package {
        import flash.display.MovieClip;
        import flash.events.*;
        public class arrayCheck extends MovieClip {
                private var myArray:Array;       
                private var myVar:uint;       
                public function arrayCheck() {
                        myArray = new Array(1,2,3,4,5,6,7,8,9,10);                       
                        myVar = 4;                       
                        addEventListener(Event.ENTER_FRAME, traceNumEnterFrame);
                }
                private function traceNumEnterFrame(event:Event) {
                        trace(myArray[myVar]);
                }
        }
}

Но что-то мне кажется, автор имел в виду другое.

gait 11.04.2010 00:00

Цитата:

Сообщение от etc (Сообщение 899518)
Ну сделайте myVar полем класса.

Существует ли возможность передать параметр, не делая myVar полем класса?

TanaTiX 11.04.2010 00:00

В доке от адоба есть пример по программированию будильника - там про пользовательские события достаточно много написано.

ЗЫ. к своему стыду так и не могу найти время чтоб все-таки изучить эту тему. Чувствую что придется изучать по ходу выполнения очередного проекта, когда припечет :(

mikhailk 11.04.2010 00:11

gait, а что на самом деле надо-то?

MrPoma 11.04.2010 00:28

Ему нужен LOLEvent.

mikhailk 11.04.2010 01:09

может и так :)
но вообще-то, если что-то в AS3 приходится делать "через голову", то скорее всего не надо этого делать. :D

gait 11.04.2010 11:32

н-да. обнаружились глобальные пробелы в знании и понимании as3:rolleyes:. может быть мне и нужен LOLEvent, но я почти ничего не понимаю, что там происходит (зачем создаётся public static const LOL, для чего нужна функция override, ну и много чего еще, выходящее за рамки этой темы). думал, что может быть есть простое решение (типа addEventListener(Event.ENTER_FRAME, traceNumEnterFrame(myVar)):D, но всё оказалось значительно сложнее :wacko:) короче, пошёл читать форум и доки, а то будет слишком много тупых вопросов. Спасибо за наводки TanaTiX (пример по программированию будильника), MrPoma (за http://www.flasher.ru/forum/showthread.php?t=136030).

mickfallout 11.04.2010 14:09

можно попробовать сделать так:
Код AS3:

package {
        import flash.display.MovieClip;
        import flash.events.*;
        public class Main extends MovieClip {
                private var myArray:Array;                       
                public function Main() {
                        super();
                        myArray = new Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);                       
                        var myVar:uint = 4;                       
                        addEventListener(Event.ENTER_FRAME, function(event:Event):void { traceNumEnterFrame(event, myVar); } );
                }
                public function traceNumEnterFrame(event:Event, myVar:int):void {
                        trace(myArray[myVar]);
                }
        }
}

только вроде использование анонимных функций - плохой стиль программирования.

MidnightOne 11.04.2010 14:44

Сколько людей уже задавались этим вопросом! :)

Есть ещё одно решение, оно "как бы" не через задний проход.
создать функцию, которая потом будет вызывать нужную уже с параметрами, и вписать её в ивент лисенер.
Код AS3:

addEventListener(MouseEvent.CLICK, BlablaCaller);
 
function BlablaCaller (e:MouseEvent){ // В скобки вообще можно вставить заглушку Null (обязательно с большой), если передаваемые лисенером данные не нужны.
    Blabla (Arg, e); // Но е можно и не передавать, это зависит от надобности.
}
 
function Blabla (arg, e:MouseEvent){
 
}

Но в этом случае придётся делать переменную полем класса. А, собственно, почему нет?

mickfallout 11.04.2010 15:17

Цитата:

Сообщение от MidnightOne (Сообщение 899600)
Есть ещё одно решение, оно "как бы" не через задний проход.
создать функцию, которая потом будет вызывать нужную уже с параметрами, и вписать её в ивент лисенер.
Код AS3:

addEventListener(MouseEvent.CLICK, BlablaCaller);
 
function BlablaCaller (e:MouseEvent){ // В скобки вообще можно вставить заглушку Null (обязательно с большой), если передаваемые лисенером данные не нужны.
    Blabla (Arg, e); // Но е можно и не передавать, это зависит от надобности.
}
 
function Blabla (arg, e:MouseEvent){
 
}


Мне кажется что создавать обработчик события который невозможно отключить - плохая идея. function BlablaCaller доступна только внутри функции, придется или писать removeEventListener внутри того же вызова функции, или не писать нигде.

MidnightOne 11.04.2010 16:32

Цитата:

Сообщение от mickfallout (Сообщение 899607)
Мне кажется что создавать обработчик события который невозможно отключить - плохая идея. function BlablaCaller доступна только внутри функции, придется или писать removeEventListener внутри того же вызова функции, или не писать нигде.

Нет. Он не внутри функции.

removeEventListener(MouseEvent.CLICK, BlablaCaller); можно написать где угодно.

mickfallout 11.04.2010 17:11

Цитата:

Сообщение от MidnightOne (Сообщение 899621)
Нет. Он не внутри функции.

не понимаю... тогда зачем вторая функция? не проще ли вместо
Код AS3:

addEventListener(MouseEvent.CLICK, BlablaCaller);
 
function BlablaCaller (e:MouseEvent){ // В скобки вообще можно вставить заглушку Null (обязательно с большой), если передаваемые лисенером данные не нужны.
    Blabla (Arg, e); // Но е можно и не передавать, это зависит от надобности.
}
 
function Blabla (arg, e:MouseEvent){
 /*тут описывать что надо делать*/
}

использовать
Код AS3:

addEventListener(MouseEvent.CLICK, Blabla);
 
function Blabla (e:MouseEvent, arg = Arg){
  /*тут описывать что надо делать*/
}

P.S. лучше писать полностью весь код, например так:
Код AS3:

package {
    import flash.display.MovieClip;
    import flash.events.*;
    public class Main extends MovieClip {
        private var arg:String="Argument";
        public function Main() {
            super();
            stage.addEventListener(MouseEvent.CLICK, blabla);
        }
 
        private function blabla (e:MouseEvent, stringArgument:String = null):void {
            if (stringArgument == null)
                stringArgument = arg;
            trace(arg + " received");
            /*тут описывать что надо делать*/
        }
    }
}


Artic 11.04.2010 17:30

мне когда лениво поднимать кастомный класс я делаю так

Код AS3:

private var hash:Dictionary = new Dictionary();
...
var someButt:Sprite = new Sprite();
someButt.graphics.beginFill(0xff0000);
someButt.graphics.drawRect(0,0,50,50);
someButt.graphics.endFill();
addChild(someButt);
var thumbs:InteractiveObject = someButt as InteractiveObject;
thumbs.addEventListener(MouseEvent.CLICK,doIt);
hash[thumbs] = "argument"
 
private function doIt(event:Event):void
{
    var target:InteractiveObject = event.target as InteractiveObject;
    trace(hash[target]) // argument;
}


udaaff 11.04.2010 17:45

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

mickfallout 11.04.2010 18:21

Цитата:

Сообщение от udaaff (Сообщение 899636)
mickfallout, автор хочет передать параметр вместе с событием, т.е. сама переменная необязательно должна быть доступна в объекте, в котором вы подписываетесь на это событие.

ну в таком виде как раз локальная переменная функции(function Main) передается в обработчик. в объекте она недоступна.
Код AS3:

package {
        import flash.display.MovieClip;
        import flash.events.*;
        public class Main extends MovieClip {
                public function Main() {
                        super();
                        var localArg:String = "local Argument";
                        var handler:Function = function(event:Event):void { multiArgumentHandler(event, localArg, handler); };
                        addEventListener(Event.ENTER_FRAME, handler);
                }
                public function multiArgumentHandler(event:Event, argument:String,handler:Function):void {
                        trace("localArgument = "+ argument );
                        removeEventListener(Event.ENTER_FRAME, handler);
                }
        }
}

Цитата:

Сообщение от gait (Сообщение 899568)
думал, что может быть есть простое решение (типа addEventListener(Event.ENTER_FRAME, traceNumEnterFrame(myVar)):D

Итого: вместо
Код AS3:

addEventListener(Event.ENTER_FRAME, traceNumEnterFrame(myVar))

писать
Код AS3:

var handler:Function = function(event:Event):void { traceNumEnterFrame(myVar); };
addEventListener(Event.ENTER_FRAME, handler);

и не забывать думать о том что если подписываешься на событие - скорее всего нужно будет и отписаться.

udaaff 11.04.2010 19:03

Цитата:

и не забывать думать о том что если подписываешься на событие - скорее всего нужно будет и отписаться.
И как вы будете отписывать вне обработчика? И в чём преимущество вашего подхода перед
Цитата:

просто создать в классе дополнительное поле для хранения этого параметра.
?

mickfallout 11.04.2010 19:40

Цитата:

И в чём преимущество вашего подхода перед
Цитата:

просто создать в классе дополнительное поле для хранения этого параметра.

Очевидно в том что оно там не хранится =) Вроде это автор темы хотел передавать в обработчик локальные переменные а не я =)
А вообще такую ситуацию можно представить:
Код AS3:

package {
    import flash.display.MovieClip;
    import flash.events.*;
    public class Main extends MovieClip {
        private var counter:int = 0;
        public function Main() {
            super();
                                  addEventListener(Event.ENTER_FRAME, enterFrameHadler);
            sayHelloManyTimes("mickfallout");
            sayHelloManyTimes("udaaff");
        }
        private function enterFrameHadler(event:Event):void {
            counter++;
        }
        private function sayHelloManyTimes(name:String):void {//здоровается с заданным человеком каждый кадр до десятого
            var handler:Function = function(event:Event):void { multiArgumentHandler(event, name, handler); };
            addEventListener(Event.ENTER_FRAME, handler);
        }
        public function multiArgumentHandler(event:Event, argument:String,handler:Function):void {
            if (counter > 10)
                removeEventListener(Event.ENTER_FRAME, handler);
            trace("Hello, " + argument );
        }
    }
}


wvxvw 11.04.2010 20:11

Самый сакраментальный вопрос - а зачем? EventDispatcher хочет вызывать слушателя с одним параметром, который сам же и создает - зачем его насиловать? Если вам очень нужно больше параметров - не пользуйтесь EventDispatcher - напишите функцию, которая принимает больше параметров и вызовите ее...

Psycho Tiger 11.04.2010 21:01

А кастомные события ну никак?

Artic 11.04.2010 21:28

эээм, а чем не устроил вариант через словарь ?

mikhailk 11.04.2010 23:30

На самом деле, как я понял, автор так и не объяснил, ЗАЧЕМ ему это нужно. :)
Что конкретно он хочет реализовать с помощью передачи параметра? И почему он так уверен, что ему нужно вообще что-то куда-то передавать?

Пока это здорово смахивает на "как мне запустить второй клип из первого, чтобы он запустил третий, а третий снова запустил первый, после чего самоликвидировался, прихватив с собой второй...". Техническое решение найти можно, но в чем смысл этого зоопарка? :D

mickfallout 12.04.2010 00:19

Цитата:

Сообщение от wvxvw (Сообщение 899667)
Если вам очень нужно больше параметров - не пользуйтесь EventDispatcher - напишите функцию, которая принимает больше параметров и вызовите ее...

слишком сложно получится, насколько я это себе представляю. просто так
Код AS3:

public function addMyEventListener(type:String, listener:Function, 
                                  useCapture:Boolean = false, priority:int = 0,
                                  useWeakReference:Boolean = false,
                                  argument:*=null):void
{
    var handler:Function = function(event:Event):void { listener(argument); };
    super.addEventListener(type, handler, useCapture, priority, useWeakReference);
}

вроде не выйдет, нужно ещё removeEventListner переопределять, хранить где-то функции(var handler:Function)... Или как-то проще можно?

MidnightOne 12.04.2010 00:38

Цитата:

Сообщение от mickfallout (Сообщение 899641)
Итого: вместо
Код AS3:

addEventListener(Event.ENTER_FRAME, traceNumEnterFrame(myVar))

писать
Код AS3:

var handler:Function = function(event:Event):void { traceNumEnterFrame(myVar); };
addEventListener(Event.ENTER_FRAME, handler);

и не забывать думать о том что если подписываешься на событие - скорее всего нужно будет и отписаться.

Главное не забыть объявить myVar перед тем как создать handler.


PS: Мне кажется, в любом из предложенных случаев правильнее создать глобальную переменную и не передавать её, а просто записать-прочитать. Почему? А потому, что все эти извращения (и уж тем более кастомная функция - диспетчер событий) занимают больше памяти и процессора, чем одна маленькая переменная. Про оптимизацию забывать не стоит!

mickfallout 12.04.2010 00:40

Цитата:

Сообщение от MidnightOne (Сообщение 899718)
Главное не забыть объявить myVar перед тем как создать handler.

будет ошибка на этапе компиляции, ничего страшного.

wvxvw 12.04.2010 04:13

Цитата:

Сообщение от mickfallout (Сообщение 899712)
слишком сложно получится, насколько я это себе представляю. просто так
Код AS3:

public function addMyEventListener(type:String, listener:Function, 
                                  useCapture:Boolean = false, priority:int = 0,
                                  useWeakReference:Boolean = false,
                                  argument:*=null):void
{
    var handler:Function = function(event:Event):void { listener(argument); };
    super.addEventListener(type, handler, useCapture, priority, useWeakReference);
}

вроде не выйдет, нужно ещё removeEventListner переопределять, хранить где-то функции(var handler:Function)... Или как-то проще можно?

Зачем? Вам же дано:
Функция А вызывает функцию Б с количеством параметров 1 (одна) штука. Это категорически изменить нельзя т.как функцию не вы вызываете - следовательно оставьте ее в покое и напишите другую функцию которая будет вызывать с двумя, тремя, четырьмя и т.д. параметрами. А то, что вы написали - мне вообще не понятно зачем это нужно / что это должно делать.
Я имею в виду вот что:
Код AS3:

function callAnotherFunctionWithTwoParams(f:Function, param0:int, param1:String):void
{
    f(param0, param1);
}


Котяра 12.04.2010 09:44

Разве сложно создать кастомное собыие? флэщдевелоп их генерит почти автоматически. кастомное событие это просто "оборачивание" любого количества параметров в один объект, только со строгой типизацией.. практически тоже самое как:
Код AS3:

function setPoint1(x:int,y:int)void;
function setPoint2(point:Object)void;
setPoint1(1,2);
setPoint1({x:1,y:2});


mickfallout 12.04.2010 13:32

Цитата:

Сообщение от wvxvw (Сообщение 899775)
Код AS3:

function callAnotherFunctionWithTwoParams(f:Function, param0:int, param1:String):void
{
    f(param0, param1);
}


спасибо) что-то такой простой вариант в голову не пришёл...
Цитата:

Сообщение от Котяра (Сообщение 899800)
Разве сложно создать кастомное собыие? флэщдевелоп их генерит почти автоматически. кастомное событие это просто "оборачивание" любого количества параметров в один объект, только со строгой типизацией.. практически тоже самое как:
Код AS3:

function setPoint1(x:int,y:int)void;
function setPoint2(point:Object)void;
setPoint1(1,2);
setPoint1({x:1,y:2});


Не понимаю, как передать в событие данные из того места где подписывается обработчик? Понимаю только как создать своё событие и передать в него данные при генерации(dispatchEvent), как получить эти данные в обработчике.
Код ваш и что он делает - тоже не понял. у меня вообще генерит ошибку
Цитата:

Error: Syntax error: missing left brace ({) before the function body.
function setPoint2(point:Object)void;
а если поправить на
Код AS3:

function setPoint1(x:int,y:int):void;

генерит ошибку
Цитата:

Error: Function does not have a body.
function setPoint1(x:int,y:int):void;
если и тело добавить -
Цитата:

Error #1063: Несоответствие количества аргументов в Main/private:init/setPoint1(). Ожидалось 2, получено 1.

Котяра 12.04.2010 13:46

это был псевдокод.
Цитата:

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

mickfallout 12.04.2010 13:54

Цитата:

Сообщение от Котяра (Сообщение 899846)
это был псевдокод.

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

Неправильно Вас понял. Ну а задачу сформулировал автор топа, и её решение действительно другое,wvxvw написал.

mikhailk 12.04.2010 18:31

+1 :)

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

Но вот зачем ему это нужно именно сейчас и здесь, он молчит как партизан. :)

inozemcev 12.04.2010 18:44

Public static const нужен для того, чтобы сделать код интуитивно более понятным

например вместо MouseEvent.CLICK можно использовать просто "click" но это может быть не очень понятно поэтому принято использовать константы.

public мы определяем потому, что это событие должно быть доступно из вне.

Теперь, как все собрать воедино:
Расширяем класс event Своим Классом
Определяем public переменную
Не забываем про функцию clone

Далее все просто 1.

1.регистрируем листенер, пишем константу того класса которая диспечеризирует наше событие
2. В приемнике события указывает тип принимаемого события (в данном случае пользовательского)
3. диспетчеризируем пользовательское событие согласно внутренней логике

MidnightOne 13.04.2010 00:38

>>что-то такой простой вариант в голову не пришёл...
А я его описал ещё на прошлой странице.

dimarik 13.04.2010 00:44

Код AS3:

var handler:Function = function(event:Event):void { listener(argument); };

Тошнит уже от таких изысков.

Artic 13.04.2010 00:46

Цитата:

Тошнит уже от таких изысков.
просто тут не видят советов
я уже советовал делать через словарь ... куда проще/изящней/удобней ( конечно на случай когда лень писать кастомный Event)

dimarik 13.04.2010 00:46

Цитата:

Сообщение от Artic (Сообщение 900057)
просто тут не видят советов
я уже советовал делать через словарь ... куда проще/изящней/удобней ( конечно на случай когда лень писать кастомный Event)

От словарей тоже.

mickfallout 13.04.2010 01:20

Цитата:

От словарей тоже.
Свою ошибку насчёт var handler:Function я понял, а со словарями что? что в них плохого?

Psycho Tiger 13.04.2010 01:35

Цитата:

Сообщение от mickfallout (Сообщение 900072)
Свою ошибку насчёт var handler:Function я понял, а со словарями что? что в них плохого?

Он просто неизящен )

DnV 19.01.2012 20:41

Для передачи именно текущего объекта можно использовать замыкание:
Код AS3:

loader.addEventListener(Event.COMPLETE, function(f){return function(e:Event):void{completeEvent(e, f)}}(file));

Сценарий использования - параллельная загрузка файлов с их последующим сохранением под своими именами.
Вместо этого, конечно, можно наследовать URLLoader и хранить каждый файл в экземпляре класса загрузчика.


Часовой пояс GMT +4, время: 03:07.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.