Me envían un correo diciéndome que tienen un menú con diversos botones y les gustaría que al momento de recibir el evento MouseEvent.CLICK que este incluya parámetros propios para así poder identificar el botón que fue.
Esta no es una buena planificación, pero en todo caso me parece un buen ejemplo para hablarles de el tema de custom Events.
El código que aquí presento es únicamente para mostrarles el ejemplo pero NO se los recomiendo ya que tiene distintos problemas de buena programación así como leaks de memoria.
Creemos nuestros menú:
Código :
import flash.display.MovieClip;
import flash.display.Graphics;
var total:uint = 3;
var boton:MovieClip;
var g:Graphics;
for(var i:uint=0;i<total;i++){
boton = new MovieClip();
g = boton.graphics;
g.beginFill(0xFF0000);
g.drawRect(0, 0, 100, 80);
g.endFill();
boton.y = 100;
boton.x = (i * 110) + 100;
addChild(boton);
}
En este ejemplo si agregamos un addEventListener al botón no vamos a poder alcanzarle nuestros propios parámetros que de hecho es el indice del botón en el menú siendo 0 el primero.
La solución es crear nuestro propio tipo de MovieClip:
Código :
package {
import flash.display.MovieClip;
public class MiPropioMC extends MovieClip
{
public function MiPropioMC(){ super();
}
}
}
Teniendo esto podemos crear instancias de MiPropioMC en vez de un MovieClip pero aun no solucionamos el tema del parámetro en el evento.
Primero hay que crear el evento:
Código :
package
{
import flash.events.Event;
import flash.events.MouseEvent;
public class MiPropioEvent extends MouseEvent
{
public static const CLICK:String = "mipropio_click";
public var miIndice:uint;
public function MiPropioEvent(type:String, indice:uint /*los demas parámetros no los vamos a utilizar en esta oportunidad*/)
{
miIndice = indice;
super(type);
}
override public function clone():Event
{
return new MiPropioEvent(type, miIndice);
}
}
}
Luego modifiquemos nuestra clase del MovieClip:
Código :
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class MiPropioMC extends MovieClip
{
public var indice:uint;
public function MiPropioMC()
{
super();
addEventListener(MouseEvent.CLICK, miDispatcher);
}
private function miDispatcher(e:MouseEvent):void
{
dispatchEvent(new MiPropioEvent(MiPropioEvent.CLICK, indice));
}
}
}
Ya con esto tenemos, ahora nada mas nos queda modificar nuestro menú:
Código :
import flash.display.Graphics;
var total:uint = 3;
var boton:MiPropioMC;
var g:Graphics;
for(var i:uint=0;i<total;i++)
{
boton = new MiPropioMC();
g = boton.graphics;
g.beginFill(0xFF0000);
g.drawRect(0, 0, 100, 80);
g.endFill();
boton.indice = i;
boton.y = 100;
boton.x = (i * 110) + 100;
boton.addEventListener(MiPropioEvent.CLICK, mandaTrace);
addChild(boton);
}
function mandaTrace(e:MiPropioEvent):void
{
trace (e.miIndice);
}
No se como hago, pero me complico en las cosas simples y resuelvo las complejas con facilidad. Parece que a ti te pasa igual, porque la solución que me propones tiene 2000 lineas mas que la mia ja ja ja ja ja ja (claro que estas dibujando los botones y todo eso).
Saludos Por:chiste
jejeje
Lo que me gusta de este foro es que siempre mis posts como orden y formato son una mierda pero cada vez que lo visito mis posts estan mas nice jejeje
Para el que se tome el trabajo, gracias! Por:fernando
ei fernando, gracias por el ejemplo...justo estaba pensando en eventos personalizados
Estoy utilizando un cursor personalizado, no es un cursor con dibujito diferente, sino es un movieclip de 1x1px cuya posicion es diferente, pero relativa a la posicion del "cursor real", el cual es evaluado por un hitTest dentro de un bucle para comprobar si alguna instancia de "boton" esta haciendo contacto con el.
Se me ocurre que la forma mas ordenada es usando eventos personalizados, pero para serte sincero, no tengo idea de como lograrlo. Por:m33toh
Lo mejor seria que hagas un listener para un MouseOver al boton. Es muchisimo mas limpio. Por:fernando
Si pues, usaria eso, en el caso que pudiese utilizar el cursor de sistema, pero el cursor que necesito, como te menciono, esta en una posicion distinta, pero relativa a este. Por:m33toh
Bueno, estuve revisando a detalle tu Tip pero me pregunto: si lo que quieren es identificar a partir del indice a cada botón y así saber cual fue presionado...
¿No bastaría con asignar dentro del loop que construye al menú un id a cada botón (name) y detectarlo a partir de event.target.name propio de MouseEvent.MOUSE_DOWN?
Son solo un par de lineas extra que harían lo mismo que tu evento creado. Por:M@U
var total:uint = 3;
var boton:MovieClip;
var g:Graphics;
for(var i:uint=0;i<total;i++){
boton = new MovieClip();
g = boton.graphics;
g.beginFill(0xFF0000);
g.drawRect(0, 0, 100, 80);
g.endFill();
boton.y = 100;
boton.x = (i * 110) + 100;
//++ Agregamos el nuevo codigo
boton.name = "boton"+i;
boton.addEventListener(MouseEvent.CLICK, BotonClick);
//--
addChild(boton);
}
function BotonClick(event:MouseEvent):void{
trace(event.target.name);
} Por:tufik2
Como el ejemplo anterior, vemos que solo tuvimos que agregar 2 lineas mas y la funcion.
con eso no extraen el indice si no un nombre que deberian parsear. No le puedes asignar una propiedad fuera de la clase porque esa clase no es dynamic.
Al final es un ejemplo de eventos propios y definitivamente no es un tip de como generar un menu. Por:fernando
Tomando el ejemplo de tufik~ puedes quitar la cadena "boton" a name, o en su defecto al querer extraer el indice utilizas un substring en este y forzas a Number.
O puedes crear un Vector bidimensional en el cual para el primer nivel asignas los nombres de los elementos, y para el segundo añades el indice. Al hacer click detectas el nombre de instancia de lo que has pulsado, utilizas esta para buscar dentro del Vector, subes un nivel y ahí estará nuevamente el indice. Por:M@U
o puedes crear un Dictionary de clases personalizadas que guarden una referencia al botón...
jejeje lo del substring funcionaria y nadie dice que no.
Repito, este es un ejemplo de "incluir parámetros propios en los eventos de Actionscript 3" y no "como devolver el indice de un botón".
Además un substring is shitty programming asi que no me vengan que esos hacks no son buenos.
En fin... también cuando quieren verle 3 pies al gato... Por:fernando
Gracias por la propuesta Fer, justo en la clase del sábado me preguntaron lo mismo, pero era un curso de AS3 básico (mencionar Custom Events hubiera sido lo mismo que abrir la caja de Pandora).
Lo que resolvimos fue usar una función intermedia. Aunque también es posible agregar una propiedad al vuelo a los MC y ya con eso hacer referencia al parámetro en mi caso un String que recibía un constructor de un URLRequest.
Si me permites un comentario creo que te viste muy Flexer para un problema Flasher, o para no despertar polémica con esto creo que te viste muy Pro para algo más Light Por:eparada
Fer, no había visto tu último comment. Creo que estabas escribiendo al mismo tiempo que yo y es cierto tienes razón en aclarar tu postura haciendo referencia al título de tu post "Incluir parámetros propios en los eventos de Actionscript 3". Por:eparada
Pff! Lo del substring es un ejemplo, igual puedes asignarle como nombre su propio indice o utilizar Vectores/Arrays para almacenarlos... Bueno, mi punto era que hay maneras mas simples que logran lo mismo, y mientras cada una funcione, parece que no hay mayor problema.
Como sea, muestras una buena manera para pasar (en este caso indices) parámetros a través de un evento. Felicidades es un muy buen Tip.
Por cierto, ¿ya probaste que el código de arriba funcione? Por:M@U
En algo en lo que si soy muy pesado es cuando de buenas prácticas de programación se trata.
Utilizar un substring soluciona el problema pero no es buena programación, utilizar el indice como nombre sin concatenarlo tampoco ya que perderias el data type de este.
Ya me dieron una idea para un proximo articulo. Thnx! Por:fernando
No he probado que el código de arriba funcione pero según el compilador de mi cerebro si funciona bien en flash. Por:fernando
Okey! Comprendo lo de forzar a Number, de hecho si lees veras que el ejemplo lo tome del código que posteo tufik~ y que yo ya había sacado un pie del tema, pero tu lanzaste la piedra nuevamente ¿que me dices de utilizar un Vector para ello?, o de simplemente utilizar event.target.name. Mas simple y directo que crear un evento.
Ooh, y sin duda decir que tienes un compilador mental tiene mucho mas éxito con las chicas que admitir que si lo probaste. Por:M@U
Por supuesto que el Vector funcionaría aunque este no sería bidimensial.
Y pues no se con que chicas sales tu pero con las que yo salgo no saben de compiladores... Por:fernando
Fernando, si lo que quieres es incluir parámetros propios en los eventos, lo que se hace es extender la clase Events, no extender la clase button. Ver "Parssing Arguments with Events" que es algo sustancialmente distinto a lo que tú planteas Por:Eliseo2
Parace que algunos no comprendieron, aqui fernando usa como ejemplo el indice, pero puedes agregar infinidad de parametros que necesites... no perdamos el foco
:glups: tienes razón, Fernando.
Volviendo al problema, creo que la mejor solución es extender la Clase button y hacerla dynamic. Con eso ya funcionamos como "toda la vida" Por:Eliseo2-blog
@eliseo2, seria mejor utilizar la clase MovieClip en vez de botón que ya es dinámica.
A mi parecer ninguna clase de flash deberia ser por defecto dinámica ya que pierde todo sentido de type checking y puede hacer que el codigo sea un desmadre.
Por mas que MovieClip sea dynamic yo si generaría una clase propia con mi propiedad asi tengo mas control por lo que mi clase contiene.
No siempre la mejor solución es la solución fácil lamentablemente. Por:fernando
Si extiendo de Button, no tengo que controlar el rollOver y el rollOut para que cambie de frame y ya tengo en onClick.
Código :
public dynamic class CustomButton extends Button{
....
}
Aunque coincido contigo en que lo suyo sería no hacer nuestro CustomButton dinámico sino crear unas funciones getter/setters
Respecto a que ninguna clase de flash debería ser por defecto dinámica, creo que sólo lo es la clase MovieClip. La verdad es que yo hubiera sugerido a Adobe que creara sus clases con la propiedad "arg", p.e. para poder usarla a convenir, pero ya es otro tema. Por:Eliseo-blog