Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Создание функций в цикле (http://www.flasher.ru/forum/showthread.php?t=196248)

HorusWM 21.03.2013 13:37

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

var i:int;
 
for (i = 0; i < 10; i++)
{
    var btn:UIButton;
 
    btn = new UIButton();
    btn.id = i;
    btn.handler = function():void
                      {
                          trace(btn.id);
                      }
}

На примере этого цикла каждой кнопке присваивается id, соответствующий i и мне нужно выводить при нажатии на нее ее id, но при нажатии на любую кнопку всегда выводится номер 9 (последний).
Помогите, пожалуйста, сделать корректное создание хендлеров с выводом идентификатора его кнопки.

bav 21.03.2013 13:51

Анонимные функции – зло. Создайте одну функцию.
Код AS3:

function buttonHandler(e:MouseEvent):void
{
  var btn:UIButton = e.target as UIButton;
  if (bth)
    trace(btn.id);
}
 
var i:int;
for (i = 0; i < 10; i++)
{
    var btn:UIButton;
 
    btn = new UIButton();
    btn.id = i;
    btn.addEventListener(MouseEvent.CLICK, buttonHandler);
}


HorusWM 21.03.2013 13:59

Цитата:

Сообщение от bav (Сообщение 1126167)
Анонимные функции – зло. Создайте одну функцию.
Код AS3:

function buttonHandler(e:MouseEvent):void
{
  var btn:UIButton = e.target as UIButton;
  if (bth)
    trace(btn.id);
}
 
var i:int;
for (i = 0; i < 10; i++)
{
    var btn:UIButton;
 
    btn = new UIButton();
    btn.id = i;
    btn.addEventListener(MouseEvent.CLICK, buttonHandler);
}


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

caseyryan 21.03.2013 14:02

Цитата:

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

HorusWM 21.03.2013 14:09

Цитата:

Сообщение от caseyryan (Сообщение 1126170)
Собственно, чем тогда вообще помогут эти кнопки?
Не может быть того, чтобы кнопки можно было нажать мышью, но при этом нельзя было повесить никаких слушателей. По-моему только с SimpleButton какая-то фигня подобная

Кнопки наследуются от общего класса объектов, который не наследуется от классов экранных объектов, а лишь хранит информацию о массиве пикселей, которые идут в отрисовку, позиции, где их рисовать, порядке отрисовки, bound-бокса объекта и т.п. А слушатель можно повесить только на дисплей обджект, насколько я помню. Чем помогут? На мой взгляд copyPixels самый быстрый способ отрисовки, во всяком случае спрайты и мувиКлипы у меня сильно грузили сцены.

silin 21.03.2013 14:42

я тоже не понял прикола с невозможнстью повесить мышиные слушатели при том, что 'нужно выводить при нажатии на нее ее id'
по сути вопроса в этом анонимном handler'е видна var btn:UIButton, которая после отработки цикла естественно указывает на последний, а нужна ссылка на конкретный экземпляр
т.е. если нужен изврат с определением handler именно в цикле, то как-то так это может быть
(это только для посмотреть, здесь конечно логичнее этот handler в самом UIButton и определить)
Код AS3:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite
        {
 
                public function Main():void
                {
                        var i:int;
 
                        for (i = 0; i < 10; i++)
                        {
                                var btn:UIButton;
 
                                btn = new UIButton();
                                btn.id = i;
                                btn.y = i * 25;
                                addChild(btn);
                                btn.handler = function():void
                          {
                                  trace("this.id: " + UIButton(this).id);
                                  trace("btn.id: " + btn.id);
                          }
                        }
                        // чтобы как-то посмотреть работу btn.handler
                        this.addEventListener(MouseEvent.CLICK, this_click);
                }
 
                private function this_click(e:MouseEvent):void
                {
                        var btn:UIButton = e.target as UIButton;
                        btn.handler();
                }
 
        }
 
}
import flash.display.Sprite;
class UIButton extends Sprite
{
        public var id:int;
        public var handler:Function;
        public function UIButton()
        {
                graphics.beginFill(0x0);
                graphics.drawRect(0, 0, 60, 20);
 
        }
}


AlexLucas 21.03.2013 14:43

А на клик вы водписываете stage или другой контейнер, и потом смотрите где клик упал, и именно тот объект который находится под курсором и ловит его ?

in4core 21.03.2013 14:44

Цитата:

Анонимные функции – зло
А вы вкурсе, что в той же джаве - анонимные функции используются так же охотно, как и методы класса? Кроме того, есть еще и анонимные классы - которые тоже используются на ура!
Так кто же прав, когда GC одинаков почти в этих 2х языках?

HorusWM 21.03.2013 14:47

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

Цитата:

Сообщение от AlexLucas (Сообщение 1126179)
А на клик вы водписываете stage или другой контейнер, и потом смотрите где клик упал, и именно тот объект который находится под курсором и ловит его ?

Именно так и сделал, AlexLucas )
Цитата:

Сообщение от HorusWM
Хотя, вы натолкнули меня на одну идею - проверять объект, находящийся под курсором, за это спасибо)


AlexLucas 21.03.2013 15:03

А если объекты накладываются друг на друга, как вы вычислите кто ловит событие ?

silin 21.03.2013 15:06

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

HorusWM 21.03.2013 15:13

Цитата:

Сообщение от AlexLucas (Сообщение 1126185)
А если объекты накладываются друг на друга, как вы вычислите кто ловит событие ?

Вопрос с перекрытиями у меня решен давно, событие ловит последний отрисованный в этих координатах (вернее хитбокс этого экземпляра).

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

bav 21.03.2013 15:31

in4core, прав дебаггер, который при возникновении ошибки сможет сказать в какой функции она произошла. И окей, специально для вас поправлюсь: я считаю, что использование анонимных функций в ActionScript 3.0 – зло.

GBee 21.03.2013 15:46

Цитата:

А вы вкурсе, что в той же джаве - анонимные функции используются так же охотно, как и методы класса? Кроме того, есть еще и анонимные классы - которые тоже используются на ура!
Так кто же прав, когда GC одинаков почти в этих 2х языках?
Можно пример анонимной функции в джаве?

in4core 21.03.2013 16:32

Цитата:

Можно пример анонимной функции в джаве?
Нельзя, их там нет, планируется в JDK8. На скорую руку писал, - а вот классы есть, как и сказал. Однако даже если так, в чем разница то?

caseyryan 21.03.2013 16:59

Цитата:

Можно пример анонимной функции в джаве?
тоже хотел задать это вопрос ) да ответ не заставил себя долго ждать

Цитата:

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

cleptoman 21.03.2013 17:00

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

in4core 21.03.2013 18:24

Цитата:

Так что нормальный проггер всегда по возможности будет этого избегать.
Откуда профит? Во-первых этого ВСЕГДА можно избегать это раз, во вторых - действительно откуда профит? У меня 2 знакомых Дяди* джависта, они уже 30 лет прогят. Причем один полностью отказывается от анонимности, второй - говорит, что вы все дураки, и анонимные классы это тру и оч удобно !

caseyryan 21.03.2013 19:14

Цитата:

они уже 30 лет прогят
Это ни о чем не говорит. Джава не такой старый язык. Так что хоть 30 лет он прогит, хоть 50, значения не имеет.

Цитата:

Откуда профит?
Оттуда что код, в котором присутствует избыточное количество разных фигурных скобок (в том месте где этого можно избежать), и вложенных конструкций, выглядит как куча мусора. И читается так же.
Цитата:

Во-первых этого ВСЕГДА можно избегать
Голословное утверждение. Технически да, но некоторые организации используют такой стиль в своих разработках. Хочешь не хочешь, а писать будешь так как потребуют.

Цитата:

Причем один полностью отказывается от анонимности, второй - говорит, что вы все дураки, и анонимные классы это тру и оч удобно !
Какой из них круче и авторитетнее? )

Bgg 21.03.2013 19:22

Про сравнение анонимности как-то товарищ expl писал:
Цитата:

Сообщение от expl (Сообщение 1119476)
Угу, по-крайней мере работают с теми же проблемами и с тем же захватом контекста, что и анонимки.


В C#, F#, Ocaml, Python, Java(совсем недавно) тоже есть анонимные функции(лямбды) и там это хорошо
Но:
1. В этих языках они чаще используются не чтобы обработать что-то асинхронно по месту, а чтобы лаконично завернуть функциональную обработку данных
2. В этих языках есть оптимизации лямбды (например по возможностьи несоздание второго экземпляра лямбды), либо проблемы с лямбдами меркнут на фоне общей тормознутости языка (как в Python)
3. Даже в Python запретили делать анонимки размером больше одного выражения
Потому что читабельность падает!

Почему анонимки в AS3 плохо:
- не первый раз здесь это говорю, но на одном проекте после истребления анонимок потребление памяти упало с 800 до 200 Mб. Вобщем, надо быть _очень_ аккуратным, чтобы ничего не потекло при использовании анонимок
- нет никаких оптимизаций - создаются при каждом упоминании, захватывают весь контекст, даже если не надо, не обрабатываются JIT-компилятором
- падает производительность - просто доступ к обычным переменным становиться медленнее в разы(!)
- читабельность ухудшается.


Nooob 22.03.2013 01:53

По вопросу.
Ссылка на btn одна в рамках создания всех анонимной функции для UIButton, поэтому в анонимной функции по этой ссылке будет последний экземпляр.
Как сделать для каждой анонимной функции свою ссылку? вызвать метод аргументом которого будет нужная ссылка на нужный экземпляр, например:
Код AS3:

for (var i:int= 0; i < 10; i++)
{
        var btn:UIButton = new UIButton();
        btn.id = i;
        btn.handler = function (btn):Function
        {
                return function () {
                        trace(btn.id)
                };
        }(btn);
}

Это будет работать, но так делать нельзя. Почему?
1. бережем память на компьютере пользователя (каждый экземпляр UIButton = новый handler, и если в анонимной функции используется что-то кроме аргументов которые передаются в неё, то она некогда не отчистится из памяти)
2. бережем глаза и свой мозг, так как никаких удобных инструментов (подсветка, переходы по F3) никакая среда разработки не предоставит

как это усовершенстовать?
Код AS3:

for (var i:int= 0; i < 10; i++)
{
        var btn:UIButton = new UIButton();
        btn.id = i;
        btn.handler = handlerUIButton;
}
 
function handlerUIButton(btn:UIButton):void
{
        trace(btn.id);
}

один метод для всех вызовов handler во всех экземплярах UIButton, при вызове нужно передать того кто вызывает (из самомого себя handler(this))

Всё вроде хорошо, но если слушателей много, а вызывается всего один?
Такак как этот объект не DisplayObject, Нужно унаследоваться от EventDispatcher (или имплементировать методы интерфейса IEventDispatcher и реализовать их с методами экземпляра EventDispatcher) при вызове дергать dispatchEvent(new MouseEvent(MouseEvent.CLICK));, а подписываться так же как и к DisplayObject btn.addEventListener(MouseEvent.CLICK, onClick);


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

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