java.blogs - Blog: James Weaver's JavaFX Blog (www.javablogs.com)
javafx: Sample Code: Dynamic menu with alert window (community.livejournal.com)
InformIT: Java Reference Guide > JavaFX Example (www.informit.com)
Java FX Script, primeros pasos - Parte 3 (blogs.sun.com)
Antes que nada, pido perd?n por no respetar la frecuencia de publicaci?n que promet?, pero esta semana tuve un problema familiar y se me atras? todo el trabajo. Sin m?s excusas, ahora si, la ?ltima entrega de la "referencia" de JavaFX script. En la primera y la segunda entrega en conjunto, ya conocimos:
- Las caracter?sticas y el prop?sito de este lenguaje.
- Los tipos primitivos
- Declaraci?n de variables
- Expresiones
- Manejo de cadenas de caracteres
- Arreglos
- El operador de selecci?n
- Queries sobre arreglos
- Formateo de cadenas de caracteres
En esta entrega, terminaremos entonces de cubrir los t?picos de la referencia oficial de JFX Script, comenzando por la declaraci?n de clases:
En JavaFX, la declaraci?n de clases consiste en colocar la palabra reservada "class" seguida del nombre que deseamos darle. Finalmente, se coloca la lista de atributos, operaciones y funciones entre llaves, separadas por punto y coma. Si nuestra clase hereda funcionalidad de una o m?s clases, se coloca luego de su nombre la palabra reservada "extends", seguida de la lista de clases "padre" separadas por comas (a diferencia de Java, en JFXS s? existe la herencia m?ltiple):
class Persona { attribute nombre: String; attribute padre: Persona inverse Person.hijos; attribute hijos: Persona* inverse Person.padre; function obtenerIngresosFamiliares(): Number; function obtenerCantidadDeHijos(): Number; operation casarseCon(pareja: Persona): Boolean; }Atributos, funciones y operaciones:
En JavaFX un atributo se declara utilizando la palabra reservada "attribute" seguida del nombre deseado y, opcionalmente, el tipo, la cardinalidad ('?', '*' o '+') y una clausula "inverse" continuaci?n. Declarar un atributo como "inverse" de otro implica que el interprete de JFXS realizar? actualizaciones (inserci?n, borrado o reemplazo) en el atributo inverso ante una modificaci?n en el atributo original.
Los atributos multivaluados (es decir, los declarados con '*' o '+') son tratados como arreglos y, por ende, puede accederse a la informaci?n contenida en los mismos utilizando el operador de selecci?n ("[]").
La contraparte en JavaFX de los m?todos en Java son las funciones y operaciones. Las primeras representan un subconjunto puramente funcional del lenguaje, se declaran utilizando la palabra reservada "function" y solo pueden contener declaraciones de variables y una sentencia de retorno. Son especialmente ?tiles para realizar operaciones matem?ticas sencillas, por ejemplo:
function z(a,b) { var x = a + b; var y = a - b; return sq(x) / sq (y); } function sq(n) {return n * n; }
Las operaciones, por su parte, pueden contener cualquier cantidad de sentencias de control: condicionales, bucles, try and catch, etc Es decir, son bastante m?s similares a un m?todo Java tradicional que las funciones. Se declaran utilizando la palabra clave "operation" y, adem?s del nombre, debe colocarse la lista de par?metros entre par?ntesis y el tipo de retorno deseado utilizando ": tipo de retorno", por ejemplo:
operation substring(s:String, n:Number): String { try { return s.substring(n); } catch (e:StringIndexOutOfBoundsException) { throw "indice fuera de rango"; } }
A diferencia de los m?todos Java, en JFX el cuerpo de las funciones y operaciones debe definirse fuera de la clase:
function Persona.obtenerCantidadDeHijos() { return sizeof this.hijos; }As? mismo, si deseamos darle valores iniciales a los atributos, debemos hacerlo fuera de la definici?n de la clase:
import java.lang.System; class X { attribute a: Number; attribute b: Number; } attribute X.a = 10; attribute X.b = -1; var x = new X(); System.out.println(x.a); // imprime 10 System.out.println(x.b); // imprime -1Una vez definida nuestra clase, lo l?gico es que creemos una o m?s instancias de la misma, para hacer esto JFXS soporta dos mecanismos: el primero, la sintaxis cl?sica de Java y, el segundo, la sintaxis declarativa propia de este lenguaje. La sintaxis cl?sica de Java consiste en realizar una llamada al constructor de la clase, pasando los valores de los atributos en el orden en que fueron declarados. La sintaxis declarativa consiste en: abrir llaves, para cada atributo colocar el nombre, dos puntos y el valor pretendido y finalizar cerrando llaves. Veamos un ejemplo utilizando la clase "Date" de Java:
import java.util.Date; import java.lang.System; var date1 = new Date(95, 4, 23); // llamada a un constructor Java var date2 = Date { // creaci?n de un "object literal" usando sintaxis declarativa month: 4 date: 23 year: 95 };Triggers
A diferencia de Java, las clases en JFXS no poseen constructores y, en general no se utilizan "setters" para los atributos. En vez de eso, el lenguaje provee un conjunto de triggers (similares a los de SQL) que permiten la manipulaci?n de estos datos. En pocas palabras un trigger (que en castellano vendr?a siendo algo como "gatillo") es un conjunto de instrucciones que se programan para "dispararse" en respuesta a un evento dado. Es decir, la ocurrencia del evento presiona el gatillo que inicia la ejecuci?n de las instrucciones. En JFXS pueden programarse triggers que respondan a eventos de creaci?n de objetos, inserci?n, reemplazo y borrado de valores de atributos multivaluados.
Triggers de creaci?n de objetos
los triggers de este tipo responden ante la creaci?n de un objeto del tipo declarado en la sentencia "on new nombreDeLaClase". Por ejemplo:
import java.lang.System; class X { attribute nums: Number*; } trigger on new X { insert [3,4] into this.nums; } var x = new X(); System.out.println(x.nums == [3,4]); // imprime trueEste trigger inserta los elementos 3 y 4 dentro del atributo multivaluado "numbs" de cada instancia de la clase X, al momento de su creaci?n. N?tese la utilizaci?n de la palabra reservada "this" para indicar que nos referimos a la instancia actual.
Triggers de inserci?n
Un trigger de este tipo se disparar? al momento de realizar una inserci?n en un atributo multivaluado. Por ejemplo:
import java.lang.System; class X { attribute nums: Number*; } trigger on insert num into X.nums { System.out.println("acaba de insertar {num} en X.nums en la posici?n {indexof num}"); } var x = new X(); insert 12 into x.nums; // imprime "acaba de insertar 12 en X.nums en la posici?n 0" insert 13 into x.nums; // imprime "acaba de insertar 13 en X.nums en la posici?n 1"
N?tese el uso del mecanismo de inserci?n de inclusi?n de referencias a variables encerr?ndolas entre llaves, as? como el uso de la instrucci?n "indexof ".
Triggers de borrado
Complementariamente a los triggers de inserci?n, existen los triggers que se disparan al borrarse un elemento de un atributo multivaluado:
import java.lang.System; class X { attribute nums: Number*; } trigger on delete num from X.nums { System.out.println("acaba de borrar {num} de X.nums en la posici?n {indexof num}"); } var x = X { nums: [12, 13] }; delete x.nums[1]; // imprime "acaba de borrar 13 de X.nums en la posici?n 1" delete x.nums[0]; // imprime "acaba de borrar 13 de X.nums en la posici?n 0"Nota: "num" es s?lo un nombre elegido al azar, la referencia a la variable que ser? insertada (o borrada) puede tomar cualquier nombre.
Triggers de reemplazo
Estos triggers se disparan al reemplazar el valor de un atributo por uno nuevo. En el ejemplo, "valorViejo" y "valorNuevo" son nombres elegidos al azar para las variables que tomaran los valores respectivos del elemento actual. Al igual que el nombre "num" de los ejemplos anteriores, estos nombres pueden ser cambiados a voluntad.
import java.lang.System; class X { attribute nums: Number*; attribute num: Number?; } trigger on X.nums[valorViejo] = valorNuevo { System.out.println("X.nums: se reemplazo {valorViejo} con {valorNuevo} en la posici?n {indexof valorNuevo}"); } trigger on X.num[valorViejo] = valorNuevo { System.out.println("X.num: se reemplazo {valorViejo} con {valorNuevo}"); } var x = X { nums: [12, 13] num: 100 }; x.nums[1] = 5; // imprime "X.nums: se reemplazo 13 con 5 en la posici?n 1" x.num = 3; // imprime"X.num: se reemplazo 100 con 3" x.num = null; // "X.num: se reemplazo 3 con null"Sentencias
JFXS soporta versiones similares de aquellas de Java. A saber:
if/ else: igual a la de Java, solo que requiere el uso obligatorio de llaves:
if (condition1) { System.out.println("Condition 1"); } else if (condition2) { System.out.println("Condition2"); } else { System.out.println("not Condition 1 or Condition 2"); }while: igual a la de Java, tambi?n requiere del uso de llaves obligatorio:
var i = 0; while (i < 10) { if (i > 5) { break; } System.out.println("i = {i}"); i += 1; }try, catch y throw: iguales a las de Java, pero con la declaraci?n de variables propia de JFXS. Es importante notar que en JFXS cualquier objeto puede ser "arrojado" y/o "atrapado", no s?lo aquellos que extienden "java.lang.Throwable"
try { throw "Hola"; } catch (s:String) { System.out.println("atrape un String: {s}"); } catch (any) { System.out.println("atrape algo que no es un Sting: {any}");? } finally { System.out.println("finally..."); }for: en JFXS, la sentencia for utiliza la misma sintaxis que "foreach" (una de las "list comprehensions" que vimos en la segunda parte del curso):
for (i in [0..10]) { System.out.println("i = {i}");? } // imprime solo los n?meros pares for (i in [0..10] where (i%2 == 0) ) { System.out.println("i = {i}"); } // imprime solo los n?meros impares utilizando un rango for (i in [1,3..10]) { System.out.println("i = {i}"); } // imprime el producto cartesiano for (i in [0..10], j in [0..10]) { System.out.println(i); System.out.println(j); }return: identica a la de java:
operation add(x, y) { return x + y; }break y continue: identicas a sus pares Java, solo que en JFXS no soportan el uso de etiquetas. Deben aparecer dentro de un bucle for o while:
operation foo() { for (i in [0..10]) { if (i > 5) { break; } if (i % 2 == 0) { continue; } System.out.println(i); } } operation bar() { var i = 0; while (i < 10) { if (i > 5) { break; } if (i % 2 == 0) { continue; } System.out.println(i); i += 1; } }do y do later: Permite ejecutar un bloque de c?digo JFX en un hilo en segundo plano. Normalmente, todo el c?digo JFX se ejecuta en un ?nico hilo (en particular en el hilo AWT Event Dispatch), unicamente el c?digo contenido dentro de una sentencia "do" puede ejecutarse en otro hilo:
import java.net.URL; import java.lang.StringBuffer; import java.lang.System; import java.io.InputStreamReader; import java.io.BufferedReader; // En el hilo AWT Event Dispatch var result = new StringBuffer(); do { // En un nuevo hilo en segundo plano var url = new URL("http://www.foo.com/abc.xml"); var is = url.openStream(); var reader = new BufferedReader(new InputStreamReader(is)); var line; while (true) { line = reader.readLine(); if (line == null) { break; } result.append(line); result.append("\n"); } } // Nuevamente en el hilo AWT Event Dispatch System.out.println("result = {result}");
El ejemplo anterior vemos como es posible mandar operaciones a segundo plano mientras continuamos con la ejecuci?n de nuestra aplicaci?n. En general esto es muy ?til para no interrumpir la ejecuci?n de las instrucciones propias de la interfaz gr?fica, rompiendo as? con la fluidez de la aplicaci?n. Sin embargo, el c?digo dentro de una sentencia "do" s?lo puede acceder a objetos Java que, de ser necesario, deber?n hacerse cargo de su sincronizaci?n.
La sentencia "do later", en cambio, permite una ejecuci?n asincronica del c?digo que envuelve dentro del hilo AWD, en vez de una ejecuci?n sincronica fuera del mismo (como lo hace "do"):
import java.lang.System; var saying1 = "Hola Mundo"; var saying2 = "Adios Mundo Cruel"; do later { System.out.println(saying1); } System.out.println(saying2);//imprime: Adios Mundo Cruel Hola MundoEvaluaci?n incremental
Finalmente, la cereza de la torta: el mecanismo de evaluaci?n incremental de JFXS. Este mecanismo permite que el valor de dos atributos se vincule utilizando la instrucci?n "bind", creando as? en una especie de "Observer - Observable" entre ellos. De esta forma, el valor de un atributo cambiar? cuando el atributo vinculado a este lo haga. Utilizando este mecanismo es posible encadenar los v?nculos para generar interfaces gr?ficas que respondan en formas complejas a distintos eventos.
Veamos un ejemplo sencillo:
import java.lang.System; class X { attribute a: Number; attribute b: Number; } var x1 = X { a: 1 b: 2 }; var x2 = X { a: x1.a // no incremental b: bind x1.b // incremental }; System.out.println(x2.a); // imprime 1 System.out.println(x2.b); // imprime 2 x1.a = 5; x1.b = 5; System.out.println(x2.a); // imprime 1 System.out.println(x2.b); // imprime 5Es f?cil ver que el vinculo se da entre X1.b y X2.b, n?tese que cuando el primero se actualiza, el segundo lo hace tambi?n. En el caso de las funciones, los valores que se modifican dentro de las mismas son evaluados incrementalmente (es decir, si estaban vinculados, los v?nculos tendr?n efecto). Por el contrario, dentro de las operaciones los valores no son evaluados incrementalmente.
Otra versi?n de la evaluaci?n incremental es la "perezosa" (lazy). En concordancia con su nombre, esta evaluaci?n espera que el valor sea sometido a una lectura para verificar si debe actualizarse. Es com?n el uso de este mecanismo para manipular estructuras recursivas de datos. Modificando el ejemplo anterior podemos ver la evaluaci?n perezosa en acci?n:
import java.lang.System; class X { attribute a: Number; } var x1 = X { a: 1 }; var x2 = X { a: bind lazy x1.a // a?n no se asignar? ning?n valor }; System.out.println(x2.a); // al leerlo, el valor se actualiza, e imprime 1Con esto completamos todos los elementos de mayor importancia de JavaFX Script en su versi?n interpretada. Les recomiendo, al igual que al finalizar la entrega anterior, que practiquen y se familiaricen con la utilizaci?n de los mecanismos propios de este lenguaje. Nos vemos en la pr?xima entrega.
- /Java
- javafx
All Content on InfoQ about JavaFX Script (www.infoq.com)
Sun JavaFX Preview SDK (www.pcworld.com)
JavaWorld@TW - Simple JavaFx (www.javaworld.com.tw)
????????????????
??????????JavaFX???? (publish.itpub.net)
JavaFX ?????????
JavaFXPAD - LightWeight JavaFX Tool Demo (www.javafxpad.com)