Форум 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=209153)

stepa323 15.10.2014 22:51

Обработчики циклом.
 
Здравствуйте как запустить много обработчиков на кнопки циклом? Есть магазин нужно обрабатывать кнопки делал так, но естественно не получилось, т к значение i меняется и естественно берется последнее значение.

Код AS3:

 
while(i<=10){
bt_head[i].addEventListener(MouseEvent.CLICK, function(){buyItem(head[i]);});
i++;
}


Gerbert 15.10.2014 23:01

Можно подробнее?

stepa323 15.10.2014 23:10

Цитата:

Сообщение от Gerbert (Сообщение 1173522)
Можно подробнее?

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

Gerbert 15.10.2014 23:15

А как у Вас логика построена? Много окон с картинкой, ценой и рядом кнопкой "в корзину"?

stepa323 15.10.2014 23:18

Да , вот скриншот ссылка

Gerbert 15.10.2014 23:39

Я бы вот как сделал... Создал контейнер миниокошка и для каждого описал бы json.
Потом бы при создании контейнера кидал бы в конструктор этот данные из этого json
где они бы и сохранялись в свойство? что-то типа
Код AS3:

private var _data:Object;
 
private var _textFieldOne:TextField = new TextField( );
private var _textFieldTwo:TextField = new TextField( );
 
private var _button:Button = new Button( );
 
public function Constructor( )
{
        super.addChild( _textFieldOne );
        super.addChild( _textFieldTwo );
 
        _button.addEventListener( MouseEvent.CLICK, button_clickHandler );
        super.addChild( _button );
}
 
public function setData( data:Object ):void
{
        _data = data;
        this.install( _data );
}
private function install( data:Object ):void
{
        super.addChild( data.img );
        _textFieldOne.text = data.textOne;
        _textFieldTwo.text = data.textTwo;
}
 
private function button_clickHandler( event:MouseEvent ):void
{
        super.dispatchEvent( new CustomEvent( _data ) );
}

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

Добавлено через 3 минуты
Забыл самое главное - события должны быть "всплывающими"!

stepa323 15.10.2014 23:50

Спасибо, но это наверное пока сложновато для моего понимания, я с as 2 только перешел, еще не очень разбираюсь что да как. Есть ли способ именно по клипам обработчиков пустить разом много.

Gerbert 16.10.2014 00:03

Код AS3:

var i:int = buttons.length;
while( i-- > 0 ){
        buttons[i].addEventListener( MouseEvent.CLICK, buttons_clickHandler );
}
 
private function buttons_clickHandler( event:MouseEvent ):void
{
        trace( event.target ); // будет кнопка
}

Так?

Добавлено через 1 минуту
Просто не совсем Вас понимаю..

samana 16.10.2014 00:15

Да, находите тот объект, который вызвал событие (как подсказал Gerbert) и вычисляйте его индекс в массиве:
Код AS3:

var i:int = bt_head.length;
while( i-- > 0 )
{
        bt_head[i].addEventListener( MouseEvent.CLICK, buttons_clickHandler );
}
 
private function buttons_clickHandler( event:MouseEvent ):void
{
        buyItem( head[bt_head.indexOf(e.currentTarget)] );
}


stepa323 16.10.2014 00:24

Так этот код сделает обработчики с buttons[0] n к концу выполнения цикла i будет равна нулю, то и все buttons будут с указателем i=0 же?
Код AS3:

var i:int = buttons.length;
while( i-- > 0 ){
        buttons[i].addEventListener( MouseEvent.CLICK, buttons_clickHandler );
}

но спасибо, попробую по вашим примерам сделать. Надеюсь сработает

Gerbert 16.10.2014 00:31

Вы даже не знаете как цикл работает?

samana 16.10.2014 18:57

Тогда сделайте через цикл for, чтобы ничего не отвлекало.

Павел Ткаченко 17.10.2014 22:38

Код AS3:

for (var i:int = 0; i < buttons.lenght; i++)
        buttons[i].addEventListener(MouseEvent.CLICK, onClickHandler);


gloomyBrain 19.10.2014 02:53

Эмм, народ, stepa232 на самом деле столкнулся с кривой реализацией примитивов и областей видимости в Flash Player. Давайте я поясню проблему кода из первого поста, смотрите:
Код AS3:

while(i<=10)
{
bt_head[i].addEventListener(MouseEvent.CLICK, function(){buyItem(head[i]);});
i++;
}

Итак, имеем самый обычный цикл, не ясно в чем проблема и почему работает так странно. Разбираем по пунктикам. Пунктик первый:
Код AS3:

bt_head[i]

- что нам вернет эта конструкция? Она вернет нам i-тый элемент массива.
Сейчас читайте внимательно. На каждой итерации цикла мы делаем следующее
1) берем переменную i
2) берем у переменной i ее текущее значение
3) берем массив bt_head
4) запрашиваем у массива элемент с номером, равным значению i

Зачем я так подробно все это расписываю? Затем что следующее использование аналогичной конструкции работает совсем по-другому. Смотрим:
Код AS3:

function() { buyItem(head[i]); }

Итак, имеем функцию. Функция тоже использует нашу переменную i, но почему-то в функции наша i всегда имеет одинаковое значение! Почему?!
А все просто. Потому что функция не выполняется внутри цикла, она создается внутри цикла. А выполняется она всегда строго после того, как цикл закончился.
А когда цикл закончился, i имеет значение с последней итерации (что логично).
Разбираем по пунктам, что делается на каждой итерации цикла:
1) Создаем новую безымянную функцию
2) Создаем код новой функции
- взять переменную i
- взять у i ее текущее значение
- взять массив head
- ну и дальше все как в прошлый раз
3) Нашу свежую функцию передаем в метод addEventListener в качестве аргумента.

Видите? Вся проблема в словах текущее значение.
В ActionScript переменная i почему-то не просто число, а объект, контейнер, у которого можно спросить его значение. И это большая проблема в таких вот замыканиях.

Но есть и решение. Оно некрасивое и неудобное в общем-то. Но оно есть. Нужно создать для каждой функции свой собственный контейнер для числа. Очень грубо это будет выглядеть вот так:
Код AS3:

while(i<=10)
{
    var listener:Function = getClickListener(i);
    bt_head[i].addEventListener(MouseEvent.CLICK, function(){listener();});
    i++;
}
 
...
 
function getClickListener(i:int):Function
{
    return function():void { buyItem(head[i]) };
}

Вот что тут происходит - когда мы передаем i в getClickListener, создается новый контейнер для числа. Копирование "простых" типов всегда происходит при передаче в новую область видимости. И, соответственно, в новом контейнере всегда хранится именно то значение, что нам нужно. То что было в i на момент итерации цикла.

MikroAcse 19.10.2014 11:39

Gerbert, честно говоря Вы немного поднадоели. Человек не имеет права не знать как работает цикл?
А если он не знает, то он удостоен Вашего содержательного ответа?
Идите пишите игры, программы, иначе у Вас будет социопатия.

Wormhole 19.10.2014 14:02

Цитата:

Сообщение от stepa323 (Сообщение 1173537)
Так этот код сделает обработчики с buttons[0] n к концу выполнения цикла i будет равна нулю, то и все buttons будут с указателем i=0 же?
Код AS3:

var i:int = buttons.length;
while( i-- > 0 ){
        buttons[i].addEventListener( MouseEvent.CLICK, buttons_clickHandler );
}

но спасибо, попробую по вашим примерам сделать. Надеюсь сработает

Кнопки "Купить"... их разве несколько? Кнопка одна, а значит и обработчик один. Совсем один. Зачем вам цикл? Создаете переменную, хранящую код выбранного товара, а в вызываемой функции записываете условный оператор, работающий с этим кодом. Каждый раз, когда товар в фокусе меняется, меняете и значение переменной. Так?

P.S. Ссылка неактивна, я не знаю, как у вас там все построено

Gerbert 19.10.2014 14:30

Цитата:

Gerbert, честно говоря Вы немного поднадоели. Человек не имеет права не знать как работает цикл?
Человек с пятилетним стажем?

samana 19.10.2014 14:53

Цитата:

Сообщение от Gerbert (Сообщение 1173725)
Человек с пятилетним стажем?

Gerbert, я думаю MikroAcse хотел сказать Вам следующее, что просто нет смысла понукать кого либо в незнании чего либо. Раз человек спрашивает, значит он не знает, иначе он бы и не спрашивал правда? Просто например сообщения вида: "Как вы этого не знаете?" - не несут никакого полезного свойства, они не помогают ни тому, кому нужна помощь, ни Вам, а лишь засоряют тему от начавшихся обоюдных, словесных перепалок.
Я ни в коем случае не пытаюсь "поставить Вас на место", просто хочу показать эту ситуацию со стороны.

Gerbert 19.10.2014 15:05

samana, я понимаю, что со стороны это может выглядеть,
как грубость или неадекватность.. Но дело в том, что я не вкладываю в слова отрицательных
эмоций, когда пишу их. Можно было написать -"нет" и это было бы равнозначно, но почему-то
я написал так. Возможно меня задело то, что показав человеку код, он ещё спрашивает - "а работает ли он",
вместо того, чтобы попробовать. В общем, я больше так не буду :)

nubideus 19.10.2014 16:29

Код AS3:

while(i<=10){
with({i: i}) bt_head[i].addEventListener(MouseEvent.CLICK, function(){buyItem(head[i]);});
i++;
}

Цитата:

В ActionScript переменная i почему-то не просто число, а объект, контейнер, у которого можно спросить его значение.
да не, переменная есть либо указатель на объект, либо примитив.
другое дело место хранения переменной

gloomyBrain 19.10.2014 21:47

Я о том и написал, что i должна быть примитивом, но почему-то им не является. Такие же проблемы есть в .NET (C#), только недавно пофиксили. А указателей у нас в AS3 нету, не знаю о чем вы. Равно ка и не очень понял про место хранения переменной - вы о чем?

nubideus 19.10.2014 22:55

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

Цитата:

Равно ка и не очень понял про место хранения переменной - вы о чем?
Цитата:

Всякий раз, когда начинается выполнение функции, создается ряд объектов и свойств. Во-первых, создается специальный объект с названием объект активации, который хранит параметры и все локальные переменные или функции, объявленные в теле данной функции. Напрямую обратиться к объекту активации нельзя, поскольку это внутренний механизм. Во-вторых, создается цепочка области действия, содержащая упорядоченный список объектов, для которых Flash Player или Adobe AIR проверяют объявления идентификаторов. Каждая выполняемая функция имеет цепочку области действия, хранимую во внутреннем свойстве. Для вложенных функций цепочка области действия начинается с собственного объекта активации, за которым следует объект активации родительской функции. Цепочка продолжается таким же образом, пока не будет достигнут глобальный объект. Глобальный объект создается при запуске программы ActionScript и содержит все глобальные переменные и функции.
http://help.adobe.com/ru_RU/ActionSc...0204-7f54.html

gloomyBrain 20.10.2014 00:39

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

nubideus 20.10.2014 02:37

gloomyBrain,

тут все нормально и обычно:
Код AS3:

class A{
 var b:int = 1;
 function A(){
  b = 2;
 }
 function c(){
  trace(b);
 }
}
 
new A().c(); // 2

Код AS3:

var b:int = 1;
var c:Function = function(){
 trace(b);
};
b = 2;
 
c(); // 2

а тут омг это же магические переменные-объекты

Цитата:

Такие же проблемы есть в .NET (C#), только недавно пофиксили
точно пофиксили?
Код:

int a = 1;
Action c = () => Console.WriteLine(a);
a = 2;
c(); // 2


gloomyBrain 20.10.2014 14:04

nubideus, про C# я вот об этом.
Про AS3: я нахожу Ваши примеры идентичными. Я в своем посте описал, как в Flash Player один и тот же тип данных может передаваться как по ссылке, так и по значению, что само по себе удивительно и неочевидно.
Надеюсь, на этот раз Вы поймете мою позицию по этому вопросу.

nubideus 20.10.2014 22:54

короче, написал криво, но примерно как то так оно работает
Код AS3:

var scopeStack:Vector.<Object> = new Vector.<Object>();
 
function pushscope(scope:Object):void {
  scopeStack.push(scope);
}
 
function popscope():void{
  scopeStack.length--;
}
 
function findgetprop(prop:String):*{
  for(var i:uint = scopeStack.length - 1; i >= 0; i--){
    var scope:Object = scopeStack[i];
    if(scope.hasOwnProperty(prop)) return scope[prop];
  }
  return undefined;
}
 
//...
 
var scope:Object = {};
scope.b = 1;
pushscope(scope);
var c:Function = function():void {
  var scope:Object = {};
  pushscope(scope);
 
  trace(findgetprop("b"));
 
  popscope();
};
scope.b = 2;
c(); // 2
popscope();



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

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