PDA

Просмотр полной версии : вызов метода во всех экземплярах класса без использования цикла for


derhab
09.08.2007, 15:22
Добрый день, такой вопрос...

1. есть класс кнопки
2. на сцене лежит несколько экземпляров класса (меню)
3. В конструкторе класса подписываю кнопку на прослушивание пользовательского события(customEvent). Соответствующий обрабатывающий метод определен в классе кнопки.

При клике на кнопку (в методе обработки клика) пишу dispatchEvent(customEvent). Все хорошо, но мне нужно, чтобы реагировали все экземпляры класса, а в этом случае событие обрабатывается только кнопкой на которую я кликнул. Варианты с циклом for не рассматриваются.
Я делал это в AS2, но тут ничего не получается:)

etc
09.08.2007, 15:26
Код можно?

derhab
09.08.2007, 15:47
вот:

package Classes{

import flash.events.Event;


public class ConstructorEvents extends Event
{
public static const BTN_STATUS:String = "btnStatus";


public function ConstructorEvents(type:String) {
super(type);
}



}




package Classes{

import flash.display.MovieClip;
import flash.events.Event;
import Classes.ConstructorEvents;


public class MenuButton extends MovieClip
{

public var event:ConstructorEvents = new ConstructorEvents(ConstructorEvents.BTN_STATUS);;



public function MenuButton()
{

addEventListener(ConstructorEvents.BTN_STATUS,onStatus);

addEventListener("click",onClick);
addEventListener("rollOver",onRollOver);
addEventListener("rollOut",onRollOut);

}

private function onClick(evt:Event):void
{
dispatchEvent(event);
}

private function onRollOver(evt:Event):void
{
}

private function onRollOut(evt:Event):void
{
}

public function onStatus(evt:Event):void
{
trace(evt.target.name);

}

}

}

etc
09.08.2007, 16:34
Для начала экземпляр ивента надо создавать в самом методе.
И нужно сделать класс-контейнер, который будет принимать события от кнопок и оповещать остальные.

derhab
09.08.2007, 16:43
Для начала экземпляр ивента надо создавать в самом методе.
Делал и так тоже. Что это меняет? Или это есть просто правильный подход?

И нужно сделать класс-контейнер, который будет принимать события от кнопок и оповещать остальные.
Пробовал что-то подобное, но видимо что-то не так..ладно, буду пытаться еще

etc
09.08.2007, 16:54
Делал и так тоже. Что это меняет? Или это есть просто правильный подход?
В целом это правильный подход.

derhab
09.08.2007, 17:43
И нужно сделать класс-контейнер, который будет принимать события от кнопок и оповещать остальные.

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

etc
09.08.2007, 17:48
Зачем? Класс-контейнер является диспетчером.

__i
09.08.2007, 17:48
а ты как хотел? можешь один раз в процессе сождания подписать все кнопки друг на друга... но помоемому будет просто полная лажа

derhab
09.08.2007, 17:56
можешь один раз в процессе сождания подписать все кнопки друг на друга... но помоемому будет просто полная лажа

согласен:)

etc
09.08.2007, 17:58
Ну для начала, можно в классе контейнере подписаться на btnStatus у самого себя. При этом событие должно быть всплывающим.

derhab
09.08.2007, 18:43
__etc, ты имел ввиду что класс контейнер должен расширять EventDispatcher или я не понял..?

etc
09.08.2007, 18:45
Да. Ну если у тебя кнопки лежат в спрайте, то он и так диспетчер.

derhab
09.08.2007, 18:47
кнопки лежат в MovieClip-e

рут расширяет спрайт, в нем контейнер - мувиклип, а кнопки в контейнере

etc
09.08.2007, 19:01
Ну вот мувиклип и сделать классом-контейнером.

derhab
09.08.2007, 19:26
ну вот код класса контейнера ( я сделал его спрайтом все таки)


package Classes{

import flash.events.Event;
import Classes.ConstructorEvents;
import flash.display.Sprite;

public class ConstructorContainer extends Sprite
{
private var event:ConstructorEvents;

public function ConstructorContainer()
{
event = new ConstructorEvents(ConstructorEvents.BROADCAST_ALL);;
addEventListener(ConstructorEvents.BTN_STATUS, broadcastMess);

}

public function broadcastMess(evt:Event)
{
//обращаясь конкретно к экземплярам я могу передать событие, но нельзя ли передать всем сразу?
this.startAgain.dispatchEvent(event)
this.changeBasic.dispatchEvent(event)
}


}

}
}


что то не так, видимо, я чего то не догоняю...

etc
09.08.2007, 19:38
package Classes{

import flash.events.Event;
import Classes.ConstructorEvents;
import flash.display.Sprite;

public class ConstructorContainer extends Sprite {

public function ConstructorContainer() {
addEventListener(ConstructorEvents.BTN_STATUS, broadcastMess);
for (var i:uint = 0;i < this.numChildren;i++) {
var child:MenuButton = this.getChildAt(i) as MenuButton;
if (child) {
child.addEventListener('broadcastAll', child.broadcastAllHandler);
}
}
}

public function broadcastMess(evt:Event)
{
dispatchEvent(new ConstructorEvent('broadcastAll'));
}


}

}
}

package Classes{

import flash.events.Event;


public class ConstructorEvent extends Event
{
public static const BTN_STATUS:String = "btnStatus";
public static const BROADCAST_ALL:String = 'broadcastAll';

public var menuButton:MenuButton;
public function ConstructorEvent (type:String, bubbles:Boolean = false) {
super(type, bubbles);
}



}

package Classes{

import flash.display.MovieClip;
import flash.events.Event;
import Classes.ConstructorEvents;


public class MenuButton extends MovieClip
{

public function MenuButton()
{

addEventListener(ConstructorEvents.BTN_STATUS,onStatus);

addEventListener("click",onClick);
addEventListener("rollOver",onRollOver);
addEventListener("rollOut",onRollOut);

}

private function onClick(evt:Event):void
{
var event:ConstructorEvent = new ConstructorEvent(ConstructorEvent.BTN_STATUS, true);
dispatchEvent(event);
}

private function onRollOver(evt:Event):void
{
}

private function onRollOut(evt:Event):void
{
}

public function onStatus(evt:Event):void
{
trace(evt.target.name);

}

public function broadcastAllHandler(event:ConstructorEvent):void {
if (event.menuButton != this) {
trace(this.name);
}
}

}

}

derhab
09.08.2007, 20:05
О, спасибо __etc! Щас буду смотреть.

__i
09.08.2007, 20:33
и возврашаясь к циклу, цикл в данном случае будет быстрее чем диспач событий.

vapes
09.08.2007, 20:42
контейнер слушает кнопки, кнопки слушают контейнер - все оч просто

__i
09.08.2007, 20:53
но цикл быстрее, готов поспорить на мороженое что быстрее :p

derhab
09.08.2007, 21:25
а там все равно без цикла не обходится)))


for (var i:uint = 0;i < this.numChildren;i++) {
var child:EditMenuButton = this.getChildAt(i) as EditMenuButton;

if (child) {
//trace(child)
child.addEventListener('broadcastAll', child.broadcastAllHandler);
}
}


__etc, извини канешно, а ты тестил свой код?))

etc
10.08.2007, 02:20
Нет, не тестил. Я примерную схему описал.

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

derhab
10.08.2007, 03:01
Со схемой я разобрался, спасибо.
я почему спросил..не работает код(


В классе ConstructorContainer не диспачится событие:


public function broadcastMess(evt:Event)
{
//вот тут глухо
dispatchEvent(new ConstructorEvent('broadcastAll'));
}

etc
10.08.2007, 03:08
А сам обработчик broadcastMess работает?

derhab
10.08.2007, 03:13
ага, работает

etc
10.08.2007, 10:17
Значит обработчик кнопок либо ничего не делает, либо не подписан на ивент.

silin
10.08.2007, 12:20
возможно я не вполне проникся в чем тут трабл, тока я не вижу почему бы не заставить статический диспатчер вещать события на все экземпляры..
package {
import flash.display.MovieClip;
import flash.events.*;

public class MenuButton extends MovieClip{

static private var dispatcher:ButDispatcher=new ButDispatcher();

public function MenuButton(){
dispatcher.addEventListener(ButDispatcher.BTN_STATUS, onStatus);
addEventListener("click",onClick);
addEventListener("rollOver",onOver);
}

private function onClick(evt:Event):void{
dispatcher.broadcast("click");
}

private function onOver(evt:Event):void{
dispatcher.broadcast("over");
}

public function onStatus(evt:ButEvent):void{
trace(name+":"+evt.status);
}
}
}
package {
import flash.events.*;
class ButDispatcher extends EventDispatcher {
public static var BTN_STATUS:String = "btnStatus";

public function broadcast(status:String):void {
dispatchEvent(new ButEvent(ButDispatcher.BTN_STATUS,status));
}
}
}
package {
import flash.events.Event;
public class ButEvent extends Event{
public var status:String;

public function ButEvent(type:String,status:String=null){
super(type);
this.status=status;
}
}
}

насчет того что цикл быстрее, есть большие сомнения: нативные методы (а там тот же цикл) всегда быстрее скриптовых, во всяком случае AsBroadcaster в AS2 выигрывает у цикла в таких случая в разы, здесь не проверял..

derhab
10.08.2007, 14:25
Вооот!
silin, большое спасибо, это именно то!:drinks: