About this siteFeed sources and resources
unknown (71)
2008 November 20 (9)2008 November 19 (3)2008 November 18 (2)2008 November 17 (5)2008 November 16 (1)2008 November 14 (3)2008 November 13 (3)2008 November 12 (3)2008 November 11 (10)2008 November 10 (6)2008 November 09 (1)2008 November 08 (4)2008 November 07 (2)2008 November 06 (6)2008 November 05 (3)2008 November 04 (3)2008 November 01 (1)2008 November 03 (1)
2008 October 31 (2)2008 October 29 (2)2008 October 28 (3)2008 October 27 (4)2008 October 26 (1)2008 October 24 (2)2008 October 22 (4)2008 October 21 (4)2008 October 20 (5)2008 October 17 (2)2008 October 16 (2)2008 October 15 (3)2008 October 14 (2)2008 October 13 (2)2008 October 11 (1)2008 October 10 (2)2008 October 08 (2)2008 October 07 (2)2008 October 06 (2)2008 October 03 (2)2008 October 01 (2)2008 October 23 (1)2008 October 09 (1)2008 October 02 (1)
2008 September 26 (2)2008 September 25 (3)2008 September 24 (2)2008 September 21 (2)2008 September 16 (1)2008 September 13 (1)2008 September 12 (9)2008 September 11 (10)2008 September 10 (6)2008 September 09 (7)2008 September 08 (5)2008 September 07 (2)2008 September 06 (3)2008 September 05 (6)2008 September 04 (7)2008 September 03 (5)2008 September 02 (4)2008 September 01 (6)2008 September 30 (1)2008 September 29 (1)2008 September 23 (1)2008 September 22 (1)2008 September 19 (1)2008 September 18 (1)
2008 August 31 (4)2008 August 30 (2)2008 August 29 (9)2008 August 28 (6)2008 August 27 (21)2008 August 26 (9)2008 August 25 (7)2008 August 24 (3)2008 August 23 (2)2008 August 22 (8)2008 August 21 (18)2008 August 20 (14)2008 August 19 (21)2008 August 18 (16)2008 August 17 (8)2008 August 16 (9)2008 August 15 (6)2008 August 14 (10)2008 August 13 (13)2008 August 12 (12)2008 August 11 (13)2008 August 10 (6)2008 August 09 (6)2008 August 08 (7)2008 August 07 (15)2008 August 06 (15)2008 August 05 (24)2008 August 04 (65)2008 August 03 (19)2008 August 02 (23)2008 August 01 (62)
2008 July 31 (87)2008 July 30 (12)2008 July 29 (10)2008 July 28 (4)2008 July 27 (13)2008 July 26 (3)2008 July 25 (3)2008 July 24 (2)2008 July 23 (4)2008 July 22 (11)2008 July 21 (1)2008 July 20 (20)2008 July 19 (3)2008 July 18 (3)2008 July 17 (5)2008 July 16 (6)2008 July 15 (14)2008 July 14 (8)2008 July 13 (2)2008 July 12 (2)2008 July 11 (5)2008 July 10 (17)2008 July 09 (1)2008 July 08 (6)2008 July 07 (11)2008 July 06 (1)2008 July 05 (4)2008 July 03 (5)2008 July 02 (3)2008 July 01 (14)

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 -1
 
  

Una 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 true
 
  

Este 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 Mundo

Evaluaci?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 5

Es 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 1
 
  

Con 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.

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)