Pasar parámetros al addEventListener en AS3
Hola a todos, hace poco que empece con AS3 y me he encontrado un primer problema, muy tonto pero que me ha llevado un rato solventar, por eso lo posteo por si alguien también lo ha sufrido.
Resulta que tenia varios botones en un flash y queria que abrieran links a URL.
La solución es simple
Se hace un boton, y se le pone un listener que llame a una funcion, hasta aqui wuay.
miBoton.addEventListener(MouseEvent.CLICK, navigate)
function navigate(evt:MouseEvent){
navigateToURL(new URLRequest("http://www.tusitio.com"))
}
¿Pero, que pasa si tengo 5 botones?
Tengo que hacer 5 listener y 5 funciones, una para cada boton, entonces pense, y si le paso el parametro (pagina_A_Abrir) desde el listener, asi sólo tendré una funcion.
Pues me las vi y me las desee para descubrir como coño podia pasar un parametro a través de un escuchador
yo probaba rollo
addEventListener(MouseEvent.CLICK, navigate(mipagina))
y más sintaxis pero na de na.
Al final encontre este link
http://www.yporqueno.es/blog/pasar-parametros-al-addeventlistener-en-as3
y es dónde haye la solución.
Se importa esta clase
// (c) 2007 Ian Thomas
// Freely usable in whatever way you like, as long as it's attributed.
package net.wildwinter{
public class Callback{
// Create a wrapper for a callback function.
// Tacks the additional args on to any args normally passed to the
// callback.
public static function create(handler:Function,...args):Function{
return function(...innerArgs):void{
handler.apply(this,innerArgs.concat(args));
}
}
}
}
y luego la funcion que yo he hecho es esta:
import net.wildwinter.Callback
boton1.addEventListener(MouseEvent.MOUSE_UP, Callback.create(enlaza, 'http://www.davidalvira.com'));
boton2.addEventListener(MouseEvent.MOUSE_UP, Callback.create(enlaza, 'http://www.davidalvira.com'));
function enlaza(evento:MouseEvent,dest):void {
navigateToURL(new URLRequest(dest),"_blank");
}
y tachannnnnn, ya podemos pasarle parametros a traves de un listener, o sea que sólo tenemos una función...
Asi no he tenido que ir haciendo funciones cada vez que ponia un boton, que de por si ya es más laborioso que el getURL() de AS2
Espero que os sirva de algo a alguien :D
saludos
odrakir
Bueno, yo no diría tanto. No es que haya que hacerlo todo fuertemente acoplado.
Depende más bien de la aplicación que tengas entre manos, te lo tendrás que montar de una forma u otra. Mejor que crear un clase botón nueva que extienda los botones añadiendo lo que necesitamos, es crear una clase que contenga un botón, o que contenga una lista de botones y una lista de sus respectivos enlaces.
A mi la verdad no me suele gustar heredar de las clases predefinidas, prefiero la composición.
ochionet
estoy con tpmmds cuando habla de la "goleada"
Estaría bien que alguien equilibrará la balanza.
Saludos,
psycho
Llevo siguiendo el post desde hace 2 días, en mi caso estoy haciendo el salto a as3,
pero estoy con Dazao, creo que deberían haber abierto la posibilidad de enviar parámetros
a los callbacks ya que le quita practicidad. Creo que esto como Delegate en su día lo
acabaran corrigiendo para que así sea, pero bueno solo es una opinión.
En mi caso meto los parámetros en una variable dentro del botón
tpmmds
BuenAS:
¿Hay que hacer las aplicaciones débilmente acopladas (loosely coupled)? El eterno dilema.
Yo por inercia tiendo a hacerlas lo más débilmente acopladas que puedo, sobre todo para poder reutilizar después lo que hago. En este caso concreto: ¿es necesario que el botón "sepa" lo que va a suceder cuando cliquen sobre él? Yo creo que no: su misión es informarnos de que el usuario ha pulsado, hacer el efecto mouseover/mouseout a la perfección y poco más. Por otro lado, un partidario de hacer las aplicaciones fuertemente acoplada te diría que el mejor sitio para guardar la información de lo que tiene que pasar cuando se pulse, es el propio botón.
En este hilo, gana por goleada la opción "fuertemente acoplada", ¡qué le vamos a hacer! :-)
Un saludo.
ochionet
Otra opcion es que cuando creas el objeto le pases un parametro a la clase boton, que seria la url, que guardaras dentro del objeto como una variable
Después cuando haces el evento
miBoton.addEventListener(MouseEvent.CLICK, navigate)
function navigate(evt:MouseEvent)
{
navigateToURL(new URLRequest(evt.target.variable))
}
Lo importante es el concepto... (getter, setter)
Saludos,
kingofsnake
dazao
Todos hemos dado palos de ciego los primeros días (y cuando no son tan "primeros" también). :)
Yo lo hago como ha planteado tpmmds, usando el target, pero yo en vez de usar un case, me creo una clase botón para mi, con funciones que me devuelven la url (por ejemplo en este caso) que le he dado a ese botón al crearlo, en fin, yo tampoco soy un gurú de as3, ni mucho menos. :D
saludos
dazao
mmm, pues nada, entonces siguiendo vuestros consejos tendré que mirarme lo de las funciones estáticas, como he dicho antes, soy un novato en AS3 y acabo de empezar, entonces voy buscando como hacer las cosas para que luego al reutilizarlas (que es continuamente) me lleve el menos tiempo posible.
Pense que este código podía ayudar a alguien, pero me parece que estoy dando palos de ciego :D
odrakir
Me quedo con la reflexión del post en el blog de Zarate:
Solo haría falta un tipo nuevo de botón que admita un parámetro "url" en el constructor, por ejemplo.
AS3 está pensado para hacer las cosas bien, lo cuál, para cosas rápidas puede no resultar más "sencillo". Eso sí, si lo quieres hacer pronto y mal siempre puedes recurrir a un:
boton1.addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{
navigateToURL(new URLRequest("http://www.tusitio.com"));
});
boton2...
tpmmds
BuenAS:
algún tipo de variable estática para evitar errores tontos
...festivamente, yo me suelo crear en las clases que se van a comunicar con eventos una serie de constantes estáticas para no tener que "acordarme" de cada nombre (como he dicho tengo muuuuy mala memoria) y sobre todo evitar errores al escribir. Aquí lo he hecho así por seguir con la línea del código inicial del ejemplo de dazao.
Un saludo.
juandelgado
Yo he pasado por ello también:
http://blog.zarate.tv/2008/11/06/my-groundhound-day-passing-extra-parameters-to-listeners/
Y aun no lo tengo muy claro. Si miras frameworks como PureMVC al final todo el tema de las notificaciones se gestiona con un switch en el que haces algo según el tipo de notificación que te llega, lo cual no está tan mal y va en la línea de lo que comenta tpmmds. Lo único que yo no haría es usar literales en el switch si no algún tipo de variable estática para evitar errores tontos.
Luego hay veces que uso sucios Delegates o la propiedad data, depende de la situación en particular.
tpmmds
ahí sobra el plural, esto de escribir sin pensar O:-)
dazao
mmm, pero eso es lo que yo pretendia con esta funcion no? o quizás no es asi.
Yo pretendía tener la función en un frame o incluso en un as, y asi siempre que quiera abrir un html sólo tendría que poner
boton1.addEventListener(MouseEvent.MOUSE_UP, Callback.create(enlaza, 'http://www.davidalvira.com'));
Igual lo estoy planteando mal, quiero decir, acabo de empezar con AS3 y esta claro que arrastro cosas de antes... D:
tpmmds
Hola:
Me refiero a que es utilizar la técnica del Delegate propia de AS2, en AS3. Ahora no es necesario recurrir a ella. Lo que se están creando son funciones estáticas que almacenan el parámetro, o parámetros que le pases.
Imagino que como todo, va por gustos, yo prefiero tener todo el código de un determinado evento centralizado en una única función, básicamente porque tengo muy mala memoria (la justa para pasar el día :-) ).
Un saludo.
dazao
mmm, no te entiendo?
el hecho de querer pasarle un parametro a una función para no tener que retocar continuamente otra es pensar en AS2 ?
tpmmds
...que es "pensar" en AS2, cuando se programa en AS3 :D
dazao
Cierto, pero entonces cada vez tendrías que añadir un case, mientras que de la otra manera se lo pasas directamente en el event, asi no tienes que estar tocando la funcion todo el rato
:D
tpmmds
Hola:
Otra posibilidad, más pensada en eventos AS3 que en eventos AS2:
boton1.addEventListener(MouseEvent.MOUSE_UP, enlaza);
boton2.addEventListener(MouseEvent.MOUSE_UP, enlaza);
function enlaza(evt:MouseEvent):void {
switch(Button(evt.currentTarget).name) {
case "boton1":
dest = "http://www.davidalvira.com";
break;
case "boton2":
dest="http://www.davidalvira.com";
break;
}
navigateToURL(new URLRequest(dest),"_blank");
}
En evt.currentTarget recuperas el objeto que ha escuchado el evento, o sea, el botón que se haya clicado en cada caso. En AS3 no es necesario "personalizar" cada función controladora, ya que puedes conocer quién ha despachado el evento (el target) y quién lo ha escuchado (el currentTarget). Dicho en otras palabras: en evt.target tienes el objeto que emitió el evento (en este caso, el objeto donde se ha clicado) y en evt.currentTarget, el objeto que ha "escuchado" ese evento (en este caso, coinciden el target y el currentTarget)
Un saludo.
dazao
ahora, también pienso que es un cachondeo tener que recurrir a una clase externa para pasar parametros a una funcion desde un eventlistener...