package com.view public class MyFirstComponent extends UIComponent override protected function commitProperties() : void override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void } }
En este tutorial voy a explicar los principios básicos a seguir para la creación de un componete flex. Para lograr esto vamos a crear un componente que cotenga un rectangulo que se mueva. Cada vez que este componente sea agregado a una aplicacion flex, entonces la aplciación tendrá un cuadrado que se mueva hacia la derecha. Por mas inutil que resulte este componente, me parece perfecto ejemplo didáctico. De todas maneras próximamente prometo crear componentes mas utiles y explicar como los hice.
Para empezar el tutorial debemos entender los conceptos básicos que estan presentes en todos los componentes flex, es decir, en todas las clases de flex que heredan de la clase UIComponent (que es el componente mas básico).
Parte I
Parte II
La clase UIComponente propone 5 métodos fundamentales a utilizar:
Cuando un componente es creado por primera vez por flex todos estos metodos se ejecutan en el siguiente orden:
Es importante saber que estos tres últimos métodos mencionados no se pueden invocar directamente, si queremos llamarlos debemos utilizar unas funciones pensadas para eso:
La razón de no llamar a estos métodos directamente es porque el framewor de flex debe llamarlos cuando lo considere pertinente, es decir, con los métodos invalidateProperties, invalidateSize e invalidateDisplayList del LayoutManager nosotros le decimos a flesx que porfavor los llame, a partir de ese momento flex esperará el momento adecuado para llamarlos. Esto debemos tenerlo siempre en cuanta para que no valla a darnos problemas en un futuro.
Creando nuestro componente.
Recuerden que el componente que vamos a crear se encargará de dibujar un rectangulo e irlo moviendo hacia la derecha. Para crear el componente vamos a agregar una nueva actionScript Class que llamaremos MyFirstComponent.as donde colocaremos el siguiente código:
Código MyFirstComponent.as
{
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.core.UIComponent;
import mx.skins.ProgrammaticSkin;
{
/*
Defino las variables que voy a utilizar en este componente.
*/
private var bloque : ProgrammaticSkin;
private var _timer : Timer = new Timer(50);
private var procesarBloque : Boolean = false;
public function MyFirstComponent()
{
super();
trace("constructor");
/*
Empiezo el timer y defino un handler llamado pintar para el evento
TimerEvent.TIMER que es disparado por el timer cada 50 miliseg.
*/
_timer.addEventListener(TimerEvent.TIMER,pintar);
_timer.start();
}
override protected function createChildren() : void
{
super.createChildren();
/*
Creo un ProgrammaticSkin y lo agrego a la lista de hijos del
componente.
*/
bloque = new ProgrammaticSkin();
this.addChild(bloque);
trace("createChildren");
}
/*
Utilizamos este metodo para cambiar el tamaño de nuestro componente
*/
override protected function measure() : void
{
super.measure();
trace("measure");
measuredWidth += 30;
measuredHeight += 30;
}
{
super.commitProperties();
trace("commitProperties");
/*
Debemos asegurarnos de que "bloque" este creado.
*/
if(bloque)
{
//Solo queremos aumentar la coordenada x de "bloque" si es menor a 100.
if(bloque.x<100) procesarBloque = true;
else procesarBloque = false;
/*
Esta condicional nos permite restringir los bloques que deseamos que sean procesados
esto se puede usar para mejorar el rendimiento del componente ya que de esta manera
podemos controlar la ejecucion de las porciones de codigo, no se debe ejecutar la
porcion que no sea necesaria.
*/
if(procesarBloque)
{
bloque.x++;
}
}
}
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
trace("updateDisplayList");
/*
En este punto pintamos nuestro bloque con el el ancho y alto de 200.
es importante dear de pintar a "bloque si no han ocurrido modificaciones de sus propiedads,
para eso usamos la bandera "procesarBloque" que tambien la utilizamos en el commmitproperties
*/
if(procesarBloque)
{
//bloque.graphics.clear();
bloque.graphics.lineStyle(1,0x000000,1);
bloque.graphics.beginFill(Math.random() * 20000000, 1);
bloque.graphics.moveTo(unscaledWidth,unscaledHeight);
bloque.graphics.lineTo(unscaledWidth,0);
bloque.graphics.lineTo(0,0);
bloque.graphics.lineTo(0,unscaledHeight);
}
/*
Esta funcion se llama cada 50 milisegundos.
*/
public function pintar(e : TimerEvent) : void
{
//Le digo a flex que cuando considere pertinente puede hacer
//un llamado a la funcion "commitProperties".
this.invalidateProperties();
this.invalidateDisplayList();
this.invalidateSize();
}
}
Las variable bloque será donde pintaremos todo nuestro cuadrado, un ProgrammaticSkin es una clase muy liviana que permite utilizar shapes sobre ellas, es decir, pintar lineas y rellenarlas.
La variable _timer se encargará de hacer una llamada a las funciones invalidateProperties, invalidateSize e invalidateDisplayList cada 50 milisegundos para que el cuadrado pintado se refresque visualmente y para que se le modifique su tamaño y propiedades.
La variable procesarBloque se definió para restringir los bloques de codigo que seran ejecutados cada vez que se llame al método commitproperties y updateDisplayList (ya que como estos métodos los vamos a llamar frecuentemente, es mejor que no se ejecute todo el codigo que ellos contienen constantemente.).
En el método create children debemos instanciar y agregar el ProgrammaticSkin que definimos ("bloque") al componente (para que pueda ser visualizado).
override protected function createChildren() : void
{
super.createChildren();
/*
Creo un ProgrammaticSkin y lo agrego a la lista de hijos del
componente.
*/
bloque = new ProgrammaticSkin();
this.addChild(bloque);
trace("createChildren");
}
En el método commitProperties se encargará de aumentar la propiedad "x" de la variable "bloque" para que el cuadradro que esta represente se mueva hacia la derecha.
override protected function commitProperties() : void
{
super.commitProperties();
trace("commitProperties");
/*
Debemos asegurarnos de que "bloque" este creado.
*/
if(bloque)
{
//Solo queremos aumentar la coordenada x de "bloque" si es menor a 100.
if(bloque.x<100) procesarBloque = true;
else procesarBloque = false;
/*
Esta condicional nos permite restringir los bloques que deseamos que sean procesados
esto se puede usar para mejorar el rendimiento del componente ya que de esta manera
podemos controlar la ejecucion de las porciones de codigo, no se debe ejecutar la
porcion que no sea necesaria.
*/
if(procesarBloque)
{
bloque.x++;
}
}
}
El metodo updateDisplayList se encargara de volver a pintar el cuadrado ahora que esta un podo mas a la derecha (porque commitProperties lo movio hacia la derecha.).
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
trace("updateDisplayList");
/*
En este punto pintamos nuestro bloque con el el ancho y alto de 200.
es importante dear de pintar a "bloque si no han ocurrido modificaciones de sus propiedads,para eso usamos la bandera "procesarBloque" que tambien la utilizamos en el commmitproperties
*/
if(procesarBloque)
{
//bloque.graphics.clear();
bloque.graphics.lineStyle(1,0x000000,1);
bloque.graphics.beginFill(Math.random() * 20000000, 1);
bloque.graphics.moveTo(unscaledWidth,unscaledHeight);
bloque.graphics.lineTo(unscaledWidth,0);
bloque.graphics.lineTo(0,0);
bloque.graphics.lineTo(0,unscaledHeight);
}
}
El metodo measure le da el tamaño inicial al componente.
override protected function measure() : void
{
super.measure();
trace("measure");
measuredWidth += 30;
measuredHeight += 30;
}
Luego de crear todos estos metodos debemos ejecutar la aplicacion en modo debugger (para que veamos lo que va arrojando la funcion trace).
Espero que les haya servido este tutorial, cualquier duda que tengan pueden escribirme al mail aalejo@gmail.com o dejar un comentario en la parte de abajo de esta página.
Ejemplo
lunes, 2 de febrero de 2009
Video tutorial Creacion de un componente Flex
Suscribirse a:
Enviar comentarios (Atom)
Es un muy didactico tu tutorial, muchas gracias Alejandro!
ResponderEliminar