Flex 4
Arquitectura de eventos
•
Los objetos AS que usamos en aplicaciones Flex se comunican
con otros objetos y con datos compartidos disparando eventos.
•
Un control Button declarado con MXML
–
<s:Button label=”Enviar”/>
•
Como instancia de la clase spark.components.Button, este objeto
soporta algunas propiedades y métodos que se conocen como
miembros de la clase Button.
•
Esta misma clase Button, tb puede generar algunos eventos
•
Podemos consultar estos eventos en la documentación de
application programming interface (API).
–
Podemos ir a esta documentación, colocando el curso en cualquier lugar
Gestionar eventos en MXML
•
Los eventos se pueden gestionar con:
–
gestores de eventos en objetos MXML expresados
como atributos XML
–
método addEventListener() de AS
•
Algunos componentes Flex, como clases
HTTPService, WebService y RemoteObject,
soportan otros gestores de eventos usando
Declarar events listeners en MXML
•
<s:Button label=”enviar”
•
click=”messageLabel.text=’has pinchado el
boton’”/>
•
<s:Label id=”messageLabel”/>
Gestionar eventos con funciones AS
•
private function clickHandler():void
•
{
•
... add ActionScript code here ...
•
}
•
<s:Button label=”hacer click”
Ejemplo - EventWithFunction.
•
En una aplicación ponemos una Label y un
Botón.
•
Al hacer clic en el botón, en la Label aparece
un texto.
Solución
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/>
</s:layout>
<fx:Script>
<![CDATA[
private function clickHandler():void
{
myText.text=
'You clicked the button';
}
]]>
</fx:Script>
<s:Label id="myText"/>
<s:Button id="myButton" label="Click me"
click="clickHandler()"/>
event objects
•
Cada evento que se despacha en Flex crea una
variable conocida como objeto evento.
•
El propósito de event object es compartir info
sobre la naturaleza del evento
–
nombre del evento
–
objeto disparador del evento
–
contexto del evento
–
info detallada que podemos usar para comprender
•
Para gestionar un evento y conseguir info sobre el
objeto evento, debemos crear una función
manejadora del evento diseñada para recibir el
objeto evento como argumento.
•
Cuando el evento ocurre, llamamos a la función
event handler y pasamos el evento object como su
argumento.
•
el objeto evento siempre es una instancia de la clase
AS flash.events.Event o una subclase de la clase
Event.
•
Al crear una función manejadora del evento para
recibir el objeto evento, siempre indicamos el tipo de
dato del argumento como Event
–
private function clickHandler(event:Event):void
–
{
•
Flash builder 4 puede Generar la función manejadora
–
al poner el atributo click tenemos la opción Generate Click Handler prompt
•
El resultado es una función colocada dentro de la etiqueta <fx:Script>
–
<fx:Script>
–
<![CDATA[
–
protected function myButton_clickHandler(event:MouseEvent):void
–
{
–
// TODO Auto-generated method stub
–
}
–
]]>
Propiedades de objeto event
•
type:String.
–
El nombre del evento despachado como un String
•
click, doubleclick….
•
target:Object.
–
Una referencia al objeto que ha disparado el evento
–
Como la propiedad target apunta al objeto, algunas
propiedades solo están disponibles con sintaxis
extendida.
•
el id del Button que ha disparado el evento se podría
Ejemplo
•
Creamos una aplicación en donde podamos
Solución - EventObjectProperties
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
protected function myButton_clickHandler(event:MouseEvent):void
{
myText.text=
"The " + event.type +
" event was dispatched by " + event.target.id;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/>
</s:layout>
<s:Label id="myText"/>
Herencia de clase Events
•
Los objetos Event son creados como clases que
depeden del evento disparado
–
flash.events.MouseEvent
–
MouseEvent, ResultEvent, TextEvent y muchos más
están en librerías que heredan de la clase Event
–
Cuando una subclase hereda de la superclase
Propiedades específicas
•
altKey:Boolean.
–
establece tru si Alt está pulsado cuando se dispara el evento
•
ctrlKey:Boolean.
•
shiftKey:Boolean.
•
commandKey:Boolean.
•
localX:int.
–
número de pixels desde el borde izquierdo donde el usuario ha pinchado en el objeto
que ha disparado el evento
•
localY:int.
•
stageX:int.
–
número de pixles desde el bortde izquierdo donde el usuario hace clic del escenario (en
la región de Flash Player)
•
stageY:int.
•
buttonDown:Boolean.
Qué evento conseguiré
•
Para encontrar qué clase específica disparará
un evento, podemos usar varias técnicas:
–
coloca el cursor del ratón sobre el argumento de
evento en el atributo manejador de evento en
MXML
–
depurar la aplicación e inspeccionar el objeto
evento en la vista Variables
–
leer la documentación API para la clase del evento
Depurar un objeto event
•
Ponemos un punto de interrupción en la función manejadora en
la línea de código de AS o si la función está vacía, en la línea que
cierra la función
–
private function clickHandler(event:MouseEvent):void
–
{
–
} //aqui breakpoint
•
depuramos la aplicación
•
activar el evento que llama a la función manejadora
–
clic en el botón, por ejemplo
•
cuando el punto de interrupción detenga la aplicación,
Gestionar eventos específicos
•
Para capturar info que sólo está disponible en alguna
clase extendida de eventos, debemos declarar el tipo de
dato del evento en el argumento de la función
manejadora
•
private function clickHandler(event:MouseEvent):void
•
{
•
myLabel.text=”You clicked; was the alt key pressed? “ +
•
event.altKey;
•
la propiedad altKey está disponible sólo pq el
argumento declarado como subclase soporta
esta propiedad.
•
Si el argumento de evento declarado hubiera
Ejemplo
•
Crear una aplicación para detectar si hemos
Solución - MouseEventObject
Properties
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"> <s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/> </s:layout>
<fx:Script> <![CDATA[
private function clickHandler(event:MouseEvent):void
{
myText.text="The " + event.type + " event was dispatched by " + event.target.id;
altText.text="Alt key pressed: " + event.altKey;
ctrlText.text="Ctrl key pressed: " + event.ctrlKey;
shiftText.text="Shift key pressed: " + event.shiftKey;
} ]]> </fx:Script> <s:Label id="myText"/> <s:Label id="altText"/> <s:Label id="ctrlText"/> <s:Label id="shiftText"/>
Gestionar eventos con addEventListener()
•
Podemos gestionar los eventos con este método
–
<s:Button id=”myButton” label=”enviar”
–
click=”clickHandler(event)”/>
–
myButton.addEventListener(“click”, clickHandler);
•
utilizamos el método addEventListener en lugar del
manejador de eventos de MXML
•
el primer arugmento es el nombre del evento a
escuchar
•
el segundo argumento es el nombre de la función que
Ejemplo
•
Sería lógico que el método addEventListener
se escuchara cuando la aplicación o el
Solución - UsingAddEventListener
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="app_creationCompleteHandler(event)"> <s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/> </s:layout>
<fx:Script> <![CDATA[
import mx.events.FlexEvent;
protected function app_creationCompleteHandler(event:FlexEvent):void
{
myButton.addEventListener(MouseEvent.CLICK, clickHandler); }
protected function clickHandler(event:MouseEvent):void
{
myText.text="The " + event.type + " event was dispatched by " + event.target.id;
} ]]>
</fx:Script>
<s:Label id="myText"/>
nombres de eventos constantes
•
Cada clase de eventos implementa constantes que
tienen los mismos valores que los nombres de los
eventos usados
•
Así la clase MouseEvent implementa las constantes:
–
CLICK = “click”
–
MOUSE_DOWN = “mouseDown”
–
MOUSE_UP = “mouseUp”
–
MOUSE_MOVE = “mouseMove”
–
RIGHT_CLICK = “rightClick”
•
En lugar de utilizar
–
myButton.addEventListener(“click”, clickHandler);
•
podemos usar
–
myButton.addEventListener(MouseEvent.CLICK,
clickHandler);
Eliminar event listener
•
Podemos eliminar un evento listener lanzado
con addEventListener utilizando el método
removeEventListener().
–
myButton.removeEventListener(MouseEvent.CLIC
Event Bubbling
•
Se refiere al proceso de disparo de evento a
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application
xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:VGroup id=”myGroup”>
<s:Button label=”Click me” id=”myButton”/>
</s:VGroup>
•
Cuando pinchamos en el botón, dispara un evento click.
•
Todos los eventos tienen una propiedad boolean
llamada bubbles
–
true – es el valor por defecto
•
el primer evento es disparado por el objeto que hemos pinchado,
luego su contenedor y así subimos por el árblo hasta llegar a la
propia aplicación
•
cada objeto evento tiene una propiead currentTarget que se refiere
al boejto que actualmente está disparando el evento
•
esta propiedad cambia el objeto del evento, aunque el target sigue
Detener propagación
•
Podemos parar la propagación llamando al
Ejemplo
•
En una aplicación tenemos un botón dentro de
un Vgroup
•
Todos los objetos gestionan el evento click que
dispara una función.
•
Utilizamos la función currentTarget para informar
qué objeto target es el actual en cada momento.
•
en un TextArea sacamos un log de nuestro
Solución - eventbubbling
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" click="clickHandler(event)">
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/> </s:layout>
<fx:Script> <![CDATA[
protected function clickHandler(event:MouseEvent):void
{
eventLog.text += "target=" + event.target.id +
", currentTarget=" + event.currentTarget.id + "\n\n";
} ]]>
</fx:Script>
<s:VGroup id="myGroup" left="10" top="10" width="50" click="clickHandler(event)">
Eventos Personalizados
•
Podemos usar eventos personalizados para
comunicar información y datos entre
componentes y aplicaciones.
•
Las aplicaciones Flex se construyen con una
arquitectura modular, con funcionalidades
divididas entre varios componentes
•
Cuando un componente necesita compartir info
Ejemplo
•
Creamos un componente personalizado que
muestra un RadioButton con tres
opcionesSmall, Medium, y Large.
•
Para agrupar las opciones debemos hacer un
RadioButtonGroup y como es un control NO
visual debemos colocarlo en la zona de
Solución
<?xml version=”1.0” encoding=”utf-8”?>
<s:VGroup xmlns:fx=”http://ns.adobe.com/mxml/2009”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>
<s:RadioButtonGroup id=”sizeGroup”/>
</fx:Declarations>
<s:RadioButton value=”Small”
label=”Small” groupName=”sizeGroup”/>
<s:RadioButton value=”Medium”
label=”Medium” groupName=”sizeGroup”/>
<s:RadioButton value=”Large”
•
cuando hacemos clic en una opción del radio button, el
componente compartirá info con la aplicación:
–
el usuario ha selecionado algo
–
el usuario ha selecionado un concreto bit de datos
•
Para compartir esta info, debemos:
–
Definir un evento personalizado que el componente MXML
pueda disparar
Declarar eventos personalizados
•
Declaramos eventos personalizados en un componente con la
etiqueta <fx:Metadata> y una etiqueta metadata llamada [Event].
•
<?xml version=”1.0” encoding=”utf-8”?>
•
<s:VGroup xmlns:fx=”http://ns.adobe.com/mxml/2009”
•
xmlns:s=”library://ns.adobe.com/flex/spark”
•
xmlns:mx=”library://ns.adobe.com/flex/mx”>
•
<fx:Metadata>
•
</fx:Metadata>
•
... other controls...
•
Añadimos metadata en nuestro componente
•
<fx:Metadata>
•
[Event(name=”sizeSelected”,
type=”flash.events.Event”)]
Solución
<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<s:RadioButtonGroup id="sizeGroup"/>
</fx:Declarations>
<fx:Metadata>
[
Event(name="sizeSelected", type="flash.events.Event")]
</fx:Metadata>
<s:RadioButton value="Small" label="Small" groupName="sizeGroup"/>
<s:RadioButton value="Medium" label="Medium" groupName="sizeGroup"/>
<s:RadioButton value="Large" label="Large" groupName="sizeGroup"/>
•
Creamos una aplicación MXML con un layout vertical
•
Añadimos el namespace de nuestro componente
personalizado
–
xmlns:components=”components.*”
•
Creamos una instancia de nuestro componente
personalizado
–
<components:SizeSelector id=”selector”/>
•
También lo puedes arrastrar desde la vista de
Disparar eventos personalizados
•
En el componente personalizado:
–
Creamos una instancia del evento que hemos declarado
–
establecemos su propiedad type como el nombre del
evento personalizado
•
todas las clases de eventos tienen un constructor que permite
establecer el nombre del evento como objeto a instanciar
•
var myEvent:Event = new Event(“[event name]”);
–
llenamos el evento con los datos del objeto
–
llamamos al método dispacthEvent() del componente y
Solución
•
var e:TextEvent = new
TextEvent(“sizeChanged”);
Solución componente completo
<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import mx.events.ItemClickEvent;
protected function sizeGroup_itemClickHandler(event:ItemClickEvent):void
{
var e:TextEvent = new TextEvent("sizeSelected", true);
e.text = sizeGroup.selection.value as String;
dispatchEvent(e); }
]]>
</fx:Script> <fx:Metadata>
[Event(name="sizeSelected", type="flash.events.TextEvent")]
</fx:Metadata> <fx:Declarations>
<s:RadioButtonGroup id="sizeGroup" itemClick="sizeGroup_itemClickHandler(event)"/> </fx:Declarations>
Solución en aplicación
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:components="components.*" creationComplete="application1_creationCompleteHandler(event)"> <fx:Script> <![CDATA[ import mx.events.FlexEvent;
protected function selector_sizeSelectedHandler(event:TextEvent):void
{
sizeMessage.text = "You selected " + event.text;
trace("selector event");
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{ } ]]> </fx:Script> <s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/> </s:layout>
<components:SizeSelectorComplete id="selector" sizeSelected="selector_sizeSelectedHandler(event)"/> <s:Label id="sizeMessage"/>
Clases de Eventos personalizados
•
Creamos una clase de AS para extender la
Asistente para crear clase As
•
es recomendable crear un paquete dentro de
nuestro proyecto en donde almacenar las clases
•
New - ActionScript class
–
nombre de la clase
–
modificador – public
–
Superclass – Browse – seleccionamos
flash.events.Event
–
Activamos Generar constructor
•
package events
•
{
•
import flash.events.Event;
•
public class LoginEvent extends Event
•
{
•
public function LoginEvent(type:String,
•
bubbles:Boolean=false, cancelable:Boolean=false)
•
{
•
super(type, bubbles, cancelable);
•
}
•
}
Solución clase
package events
{
import flash.events.Event;
public class LoginEventComplete extends Event
{
public var username:String;
public var password:String;
public static const LOGIN:String = "login";
public function LoginEventComplete(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, true);
trace("constructor");
}
override public function clone():Event
{
var newEvent:LoginEventComplete = new LoginEventComplete(type);
newEvent.username = username; newEvent.password = password;
trace("cloning with currentTarget: " + this.currentTarget.id);
return newEvent;
declarar nombres de eventos constantes
•
Si conocemos el nombre de los eventos que queremos
personalizar, podemos declarar nombres constantes que
sirven como MouseEvent.CLICK
•
Nos ayudan a asegurar el código para el resto de la
aplicación
–
public static const LOGIN:String=”login”;
•
lo usaremos así:
–
myComponent.addEventListener(LoginEvent.LOGIN,
Sobreescribir el método clone
•
la clase Event tiene un método clone() que se
usa para copiar el objeto Event
•
el método clone se llama cuando se redispara
un evento después de recibirlo en su función
manejadora
•
si no ponemos overrride…el compilador dará
error
Disparar una clase de evento personalizado
•
Se siguen los mismos pasos que para construir
una clase de evento
–
define un evento personalizado que establezca el
tipo como la nueva clase AS
–
crear un objeto evento cuyo tipo es la clase
evento en runtime
•
Para declarar un evento personalizado
llamado login que dispara una instancia de la
clase LoginEvent
–
<fx:Metadata>
•
En tiempo real, creamos una instancia de la
clase del evento y le pasamos el nombre del
evento en el método constructor
•
llenamos el objeto evento con datos
•
Debemos tener controles TextInput con sus
propiedades id
•
Por último, disparamos el evento
Ejemplo
•
Creamos un componente personalizado para
pedir datos al usuario con un Formulario
•
Flex 4 SDK no incluye una versión Spark para
Solución - login
<?xml version="1.0" encoding="utf-8"?>
<mx:Form xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Metadata>
[Event(name="login", type="events.LoginEventComplete")]
</fx:Metadata> <fx:Script> <![CDATA[
import events.LoginEventComplete;
private function clickHandler():void
{
var e:LoginEventComplete = new LoginEventComplete("login");
e.username = userNameInput.text; e.password = passwordInput.text; dispatchEvent(e);
} ]]> </fx:Script>
<mx:FormItem label="User Name:"> <s:TextInput id="userNameInput"/> </mx:FormItem> <mx:FormItem label="Password:"> <s:TextInput id="passwordInput"/> </mx:FormItem> <mx:FormItem>
<s:Button label="Log In" click="clickHandler()"/> </mx:FormItem>
Gestionar un evento que usa una clase de
evento personalizado
•
Podemos manejar un evento que usamos con un clase de
eventos personalizado de dos maneras:
–
con un manejador de eventos basado en MXML
–
con addEventListener()
•
Creamos una función manejadora que espera un argumento
del tipo del evento personalizado creado en la clase de AS
–
private function loginHandler(event:LoginEvent):void
•
tal vez tengamos que importar la clase
•
dentro de la función manejadora, extraemos los
datos que necesitamos
•
private function loginHandler(event:LoginEvent):void
•
{
•
messageLabel.text = “You logged as “ +
event.username +
•
Para llamar a la función manejadora usando el
manejador basado en MXML
–
<components:LoginForm
•
O podemos usar addEventListener()
–
myForm.addEventListener(LoginEvent.LOGIN,
Solución – Aplicación final
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:components="components.*"> <fx:Script> <![CDATA[ import events.LoginEventComplete;
private function loginHandler(event:LoginEventComplete):void
{
messageLabel.text = "You logged as " + event.username +
" with a password of " + event.password;
} ]]>
</fx:Script>
<s:Panel title="Please Log In" horizontalCenter="0" top="20">
<components:LoginForm id="myForm" login="loginHandler(event)"/> <s:controlBarContent>
<s:Label id="messageLabel"/> </s:controlBarContent>