Al crearse un proyecto de Flex mediante Flex Builder, se crea un archivo mxml con el mismo nombre que el proyecto. Este contiene el siguiente código:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> </mx:Application>
Esta es la aplicación principal (el tag <mx:Application> dentro del archivo .mxml con el mismo nombre que el proyecto), aún así podríamos cambiarlo (en el Flex Builder, botón derecho → Set as default application).
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="100%" width="100%">
<mx:control propiedad="valor">contenido</ mx:control>
<mx:Label x="194" y="6" text="{cmb.value}" width="94" />
<mx:DataGrid x="194" y="298"> <mx:columns> <mx:DataGridColumn headerText="Column 1" /> <mx:DataGridColumn headerText="Column 2" /> <mx:DataGridColumn headerText="Column 3" /> </mx:columns> </mx:DataGrid>
Podemos definir los tamaños de los controles en tantos por ciento respecto a su contenedor.
Dentro del cuerpo del combo crearemos objetos con las propiedades label y data. En label estará el texto que se mostrará para el elemento y dentro de data su valor asociado:
<mx:ComboBox x="130" y="60" width="103" id="cmb" > <mx:Object label="Euro" data="166"/> <mx:Object label="Dolar" data="150"/> <mx:Object label="Yen" data="3000"/> </mx:ComboBox>
Ahora, mediante ActionScript, podemos acceder al valor seleccionado del combo con un cmb.value.
De la misma forma también podemos asignar un array mediante un dataProvider:
<mx:ComboBox x="130" y="60" width="103" id="cmb" > <mx:dataProvider> <mx:Array> <mx:String>Satisfied</mx:String> <mx:String>Neutral</mx:String> <mx:String>Dissatisfied</mx:String> </mx:Array> </mx:dataProvider> </mx:ComboBox>
Podemos asignar un dataProvider de otra forma, mediante la propiedad dataProvider del control. Por ejemplo:
<mx:ComboBox id="cb_amount" dataProvider="{Currency}" prompt="Select currency..." width="150"/>
El Currency del ejemplo será un array definido en el código ActionScript: public var Currency:Array = [“US Dollars”, “Euro”];
Al tener la aplicación como layout=“absolute” podemos colocar los elementos donde queramos, siempre se quedarán ahí, aunque el explorador donde estén colocados sea redimensionado ellos seguirán con un tamaño estático. Aún así, nosotros podemos cambiar esa propiedad asignando unos márgenes, de esta forma, ya se haga más grande o más pequeño el tamaño del explorador, los controles tendrán un tamaño relativo.
Para asignar dicho márgen existen las propiedades left, right, top y bottom:
<mx:Panel layout="absolute" title="Convertidor" id="pnl" left="20" right="20" top="20" bottom="458">
Estas propiedades, en el Flex Builder, se editan desde el apartado constraints.
Hay tres formas de posicionar los controles:
Por ejemplo, colocando en el contenedor el layout como horizontal y el verticalAlgingn como middle hará que los controles se inserten en el centro del contenedor en una fila.
Crear un componente desde el Flex Builder es sencillo, sólo has de añadir nuevo componente, dar su nombre y buscar en qué elemento se basa. Una vez lo tengamos, veremos que el código es como el de una aplicación pero siendo la tag principal la correspondiente al elemento escogido.
Por ejemplo si escogemos un <mx:Panel>:
<?xml version="1.0" encoding="utf-8"?> <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="275" height="150"> </mx:Panel>
click="blurEffect.play(); myLabel.visible=true;"
<mx:Button click="funcion(event)" id="btn"/>
function funcion(e:Event):void { }
Para asignar un evento por ActionScript, como en mxml, debe de existir una función que será la que ejecute el código asociado al evento, pero esta debe de recibir un parámetro del tipo Event, por ejemplo:
public function Convert(e:Event):void
Ahora debemos crear un EventListener asociado a Convert para el evento Click del botón, esto es un “escuchador de eventos” que cuando se lance el evento Click en el botón se llamará a Convert:
boton.addEventListener(MouseEvent.CLICK, Convert);
Lo más adecuado es meterlo dentro de una función que llamaremos al acabar de crear el interface, algo así:
public function createListener():void { boton.addEventListener(MouseEvent.CLICK, Convert); }
Para que se llame tras haberse acabado de crear el interface, es decir, tras haberse acabado de ejecutar el tag Application, debemos añadir a este (<mx:Application>) la propiedad siguiente:
creationComplete="createListener();"
Existen varias clases que pueden llegar a contener controles y poder ordenarlos o tratarlos de forma específica:
Para insertar controles en un contenedor de navegación debemos insertar antes en él un contenedor corriente (p.ej. un canvas, para el título de los apartados usaremos su propiedad label). Existen los siguientes contenedores de navegación:
<mx:LinkBar x="10" y="390" dataProvider="{myViewStack}" />
Podemos definir comportamientos para los controles, otra forma de decir “comportamientos” sería “efectos”. Los efectos en Flex también tienen sus propias tags, estas no han de definirse dentro de contenedoras (paneles formularios…), sino dentro de la aplicación:
<mx:Glow id="buttonGlow" color="0x99FF66" alphaFrom="1.0" alphaTo="0.3" duration="1500"/>
Para asignarlos mediante el Flex Builder iremos a la vista por categorías de un control y se lo asignaremos en el apartado de efectos mediante su id entre corchetes. En código debe de quedar así:
<mx:Button x="155" y="10" label="Button" mouseUpEffect="{buttonGlow}"/>
Podemos asignar a un control el efecto mediante la propiedad target, el id del control deberá ir entre corchetes: target=“{myLabel}”. Sabiendo que mediante ActionScript podemos iniciar un efecto mediante idEfecto.play(), podríamos, por ejemplo, al apretar un botón se llame al play de un efecto que tiene un target asignado. (También existe el método idEfecto.pause() y el idEfecto.resume()).
Podemos crear efectos combinados, es decir, grupos de efectos que se ejecutan como si fuesen uno. Para ello usamos la tag <mx:Parallel>, le damos un id y un target, y en su cuerpo introducimos los efectos que la componen:
<mx:Parallel id="BlurMoveShow" target="{myLabel}"> <mx:Blur .../> <mx:Move ... /> </mx:Parallel>
Ahora sólo tendremos que hacer un BlurMoveShow.play() para que los efectos Blur y Move se ejecuten sobre myLabel.
<mx:Zoom id="shrink" duration="100" zoomHeightTo=".9" zoomWidthTo=".9" /> <mx:Zoom id="revert" duration="50" zoomHeightTo="1" zoomWidthTo="1" /> <mx:Button label="Pulsa!" mouseDownEffect="{shrink}" mouseUpEffect="{revert}"/>
currentState='Advanced' currentState=''
Esto lo podríamos hacer en la propiedad click de un botón, en el estado stándard: click=“currentState='Advanced'”. Y en el estado Advanced cambiaríamos el código anterior por
currentState=''
Por ejemplo, para crear una transición llamada 'myTransition' que vaya del estado inicial al 'Advanced' haremos lo siguiente:
<mx:transitions> <mx:Transition id="myTransition" fromState="*" toState="Advanced"> </mx:Transition> </mx:transitions>
Ahora debemos definir qué efecto se usará para la transición, al efecto deberemos darle un target (objeto que realizará dicha transición), para ello colocaremos su id entre corchetes:
<mx:transitions> <mx:Transition id="myTransition" fromState="*" toState="Advanced"> <mx:WipeDown duration="500" target="{myVBox}"/> </mx:Transition> </mx:transitions>
<mx:transitions> <mx:Transition id="myTransition" fromState="*" toState="Advanced"> <mx:Parallel target="{myVBox}"> <mx:WipeDown duration="2000"/> <mx:Dissolve alphaFrom="0.0" alphaTo="1.0" duration="2000"/> </mx:Parallel> </mx:Transition> </mx:transitions>
<mx:Parallel targets="{[loginPanel, registerLink, loginButton]}">
<mx:Resize duration="500" easingFunction="Bounce.easeOut"/>
<mx:Style source="styles.css"/>
<mx:Style> .myclass { color: Red } /* class selector */ Button { fontSize: 10pt; color: Yellow } /* type selector */ </mx:Style>
<mx:Label text="Label con estilo" styleName="myclass" id="lbl"/>
lbl.setStyle(“color”, “Red”);Para que un objeto que se enlace a datos (por ejemplo HTTPService) pueda acceder a una fuente de datos (por ejemplo un xml de feeds) se han de cumplir una de las siguientes premisas:
Te permite acceder a un servicio web mediate http, las propiedades más destacadas (a parte del id) son url (dirección del lugar donde se accederá) o useProxy (que indica si se usa o no un proxy).
<mx:HTTPService id="feedRequest" url="http://weblogs.macromedia.com/mchotin/index.xml" useProxy="false"/>
Deberemos hacer idHttpService.send() para que se carguen los datos. Podríamos por ejemplo hacerlo tras haberse cargado la aplicación:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="feedRequest.send()">
id del WebService.Nombre de la acción.send() Por ejemplo, vamos a hacer una llamada a la acción de un webservice llamada 'getMostPopularPosts', a la cual se le pasan los parámetros daysBack y limit:
<mx:WebService id="wsBlogAggr" wsdl="http://weblogs.macromedia.com/mxna/webservices/mxna2.cfc?wsdl" useProxy="false"> <mx:operation name="getMostPopularPosts"> <mx:request> <daysBack>30</daysBack> <limit>{combo.value}</limit> </mx:request> </mx:operation> </mx:WebService>
Para llamar a este webservice deberemos hacer:
wsBlogAggr.getMostPopularPosts.send()
Si queremos que el DataGrid se enlace a los elementos item asignaremos su dataProvider así:
dataProvider="{feedRequest.lastResult.rss.channel.item}"
Ahora deberemos enlazar sus columnas, una al título y otra a la fecha de publicación:
<mx:DataGridColumn headerText="Posts" dataField="title"/> <mx:DataGridColumn headerText="Date" dataField="pubDate" />
Ya tenemos el grid enlazado a los datos, ahora si queremos que en un texto a parte se muestre la descripción del “item” clicado sólo debemos hacer:
<mx:TextArea text="{idGrid.selectedItem.description}" />
Otro ejemplo sería el de enlazar el DataGrid al resultado de una llamada a un webservice, el dataProvider se declararía así:
dataProvider="{iDWebService.NameOperation.lastResult}"
dataProvider="{wsBlogAggr.getMostPopularPosts.lastResult}">
Las columnas seguirían teniendo el dataField que les tocase según lo devuelto por el WebService.
P.Ej. unos datos como estos:
<data> <tag> <id>0</id> <label>Prueba</label> </tag> </data>
En una lista como esta:
<mx:List dataProvider="{dataBinder.lastResult.data.tag}"/>
Se nos mostrará el elemento de la tag label, si la tag hubiese sido nombre no hubiese sido correcto.
<mx:TextInput text="{lstTags.selectedItem.id}"/>
<mx:Image source="tortuganinja.jpg"/>
<mx:Image source="@Embed('tortuganinja.jpg')"/>
[Embed(source="tortuganinja.jpg")] [Bindable] public var tortuga:Class;
Ahora, para usarla en una imágen:
<mx:Image source="{tortuga}" />
[Embed( source="assets/fancy_border.png", scaleGridTop="55", scaleGridBottom="137", scaleGridLeft="57", scaleGridRight="266" )]
<mx:Style> Button { upSkin: Embed("assets/box_closed.png"); overSkin: Embed("assets/box.png"); downSkin: Embed("assets/box_new.png"); } </mx:Style>
[Embed(source="assets/hourglass.swf")]
[Bindable] public var Hourglass:Class;
[Embed(source="assets/library.swf", symbol="BadApple")] [Bindable] public var BadApple:Class;
[Embed(source="assets/pie-yan-knee.mp3")]
[Bindable] public var Song:Class;
public var mySong:SoundAsset = new Song() as SoundAsset;
Para utilizarlas debemos añadir el archivo .ttf de la fuente en nuestro directorio de trabajo y enlazarla dentro de la etiqueta style:
<mx:Style> @font-face { font-family: sands; src: url("sands.ttf"); } </mx:Style>
Ahora ya podemos usarla en un texto:
<mx:Text fontFamily="sands" text="Hola, buenos dias!" />
Para la creación de formularios existe un elemento que nos facilitará la vida, el <mx:FormItem>. Equivale a un elemento de formulario, este contiene una Label (propiedad label del mx:FormItem) y un control que se incluye entre sus tags de inicio y cierre:
<mx:FormItem label="Subscriptions:" width="100%"> <mx:List id="userSubscriptions" rowCount="3" allowMultipleSelection="true" width="100%" dataProvider="{subscriptions}" /> </mx:FormItem>
<mx:Style> ToolTip { fontFamily: "Arial"; fontSize: 10; color: #FFFFFF; backgroundColor: #000000; } </mx:Style>
De tal mundo no es necesario mucho conocimiento. Únicamente debemos saber que para poder trabajar con el cursor tenemos la necesidad de importar en nuestro proyecto la clase: mx.managers.CursorManager.
import mx.managers.CursorManager;
CursorManager.setCursor(VariableImagen);
Los scripts se introducen dentro de la tag <mx:Application>. Se usa la tag <mx:Script> que al crearla en el Flex Builder te aparece lo siguiente:
<mx:Script> <![CDATA[ ]]> </mx:Script>
<mx:Script source="sourcecode.as"/>
Corresponde al componente <mx:Repeater> y lo que hace es emular, en sintaxis MXML un bucle for.
Por ejemplo, tenemos un array de objetos de una clase producto, esta tiene como una de sus propiedades 'name'. Ahora, lo que hacemos es enlazar el dataProvider del <mx:Repeater> al array (productsAC) y dentro de este colocamos el control que queremos que se repita:
<mx:Repeater id="productsRepeater" dataProvider="{productsAC}"> <mx:RadioButton id="buttonsArray" label="{productsRepeater.currentItem.name}" data="{productsRepeater.currentItem}"/> </mx:Repeater>
Aún más sencillo, tenemos un array (myArray) y queremos que se nos muestre dicho array en labels:
<mx:Repeater id="myRep" dataProvider="{myArray}"> <mx:Label id="myLabel" text="{myRep.currentIndex}"/> </mx:Repeater>
Como vemos, la propiedad currentIndex del Repeater corresponde al elemento en el que se está en la iteración.
Podemos crear skins para nuestros controles, por ejemplo, embeber una imágen y usarla como botón mediante los estilos:
<mx:Style> Button { upSkin: Embed("box_closed.png"); overSkin: Embed("box.png"); downSkin: Embed("box_new.png"); } </mx:Style> <mx:Button/>
El botón que se ha introducido en el código (sin id ni nada) se mostrará como una imágen (box_closed) que cuando se ponga el ratón por encima mostrará otra (box) y cuando se haga click otra (box_new).
Podemos usar el scale-9 para hacer marcos para los textos:
<mx:Style> .scale9Background { background-image: Embed("assets/fancy_background.png", scaleGridTop="55", scaleGridBottom="137", scaleGridLeft="57", scaleGridRight="266"); background-size:"100%"; } VBox { padding-bottom:50; padding-top:50; padding-left:60; padding-right:60; } </mx:Style> <mx:VBox styleName="scale9Background" width="100%" height="50%"> <mx:Text width="100%" styleName="nonScale9Background" text="This VBox has a graphical scale-9 background skin that stretches to fill the background.{'\r\r'}Notice how the corners do not scale. You can also use a preset padding value to offset your content so it appears inside the borders of the background image." /> </mx:VBox>
La VBox conteine un texto que tiene el fondo indicado con scale-9.
<mx:Model id="artwork" source="model/artwork.xml"/> <mx:DataGrid rowCount="4" dataProvider="{artwork.piece}"/>
El archivo xml tiene la siguiente estructura: 0. arwork → 1. piece → 2.name, image, price, quantity
El artwork es el elemento raíz, contiene varios pieces y cada uno con name, price y quantity, quantity es un número, igual que price, nombre es su nombre, e image es una ruta de una imágen:
<artwork> <piece> <name>The Wall</name> <image>artwork1.jpg</image> <price>250</price> <quantity>5</quantity> </piece>...
<mx:DataGrid rowCount="10" variableRowHeight="true" dataProvider="{artwork.piece}"> <mx:columns> <mx:DataGridColumn dataField="image" headerText="Image" itemRenderer="mx.controls.Image" /> <mx:DataGridColumn headerText="Name" dataField="name"/> <mx:DataGridColumn headerText="Price" dataField="price"/> <mx:DataGridColumn headerText="Quantity" dataField="quantity" itemRenderer="mx.controls.NumericStepper" /> </mx:columns> </mx:DataGrid>
Para que esto haya podido ser posible la clase del <mx:DataGrid> debe heredar de las interfaces IDropInListItemRenderer.
<mx:Component id="ImageRenderer"> <mx:VBox width="100%" height="140" horizontalAlign="center" verticalAlign="middle"> <mx:Image source="{'assets/'+data.image}"/> <mx:Label text="{data.image}" /> </mx:VBox> </mx:Component>
<mx:DataGrid rowCount="3" variableRowHeight="true" dataProvider="{artwork.piece}"> <mx:columns> <mx:DataGridColumn dataField="image" headerText="Image" width="150" itemRenderer="{ImageRenderer}"/> <mx:DataGridColumn headerText="Name" dataField="name"/> <mx:DataGridColumn headerText="Price" dataField="price"/> </mx:columns> </mx:DataGrid>
<?xml version="1.0" encoding="utf-8"?> <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="center" verticalAlign="middle" width="100%" height="140"> <mx:Image source="{'assets/'+data.image}"/> <mx:Label text="{data.image}"/> </mx:VBox>
<?xml version="1.0" encoding="utf-8"?> <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="center" verticalAlign="middle"> <mx:NumericStepper maximum="{data.quantity}"/> </mx:VBox>
<mx:DataGrid rowCount="3" variableRowHeight="true" dataProvider="{artwork.piece}"> <mx:columns> <mx:DataGridColumn dataField="image" headerText="Image" width="150"> <mx:itemRenderer> <mx:Component> <mx:VBox width="100%" height="140" horizontalAlign="center" verticalAlign="middle"> <mx:Image source="{'assets/'+data.image}"/> <mx:Label text="{data.image}" /> </mx:VBox> </mx:Component> </mx:itemRenderer> </mx:DataGridColumn> <mx:DataGridColumn headerText="Name" dataField="name"/> <mx:DataGridColumn headerText="Price" dataField="price"/> </mx:columns> </mx:DataGrid>
var nombre:String = “texto {variable} texto”;Para desarrollar con Flex a partir de Visual Studio 2008 necesitarás el plugin Ensemble.