Java FX Script, primeros pasos - Parte 4
Cuando Sun presentó JavaFX en JavaOne 2007, JFX Script era aún un lenguaje interpretado. Sin embargo, desde un primer momento se aclaró que esto era sólo temporal, mientras el lenguaje pasaba de ser el resultado de la investigación personal (F3, de Chris Oliver) a un producto a ser introducido en el mercado. Es así como, después de un lapso de tiempo, JFX Script pasó de ser un lenguaje interpretado, a un lenguaje compilado, principalmente porque uno de las características principales que Sun pretende para las aplicaciones escritas en este lenguaje es un nivel de performance mayor que aquellas escritas en Javascript o ActionScript (de hecho, en los benchmarks realizados por Chris Oliver, el rendimiento de JFX Script fue 12 veces mayor que el de ActionScript.
Al cambio de categoría del lenguaje se sumaron algunos cambios en la sintaxis, los cuales revisaremos hoy, siguiendo la guia de migración de Planet JFX (simplemente porque fue una de las más completas que conseguí), como para dar por terminada esta parte, y comenzar luego con ejemplos algo más complejos y aggiornados.
Operaciones
Antes: el lenguaje diferenciaba entre funciones y operaciones.
class Foo {
function times2(x) { return x * 2; }
operation print(s) { System.out.println(s); }
}
|
Ahora: La sintaxis actual fusiona los dos conceptos en uno único: el de función, y utiliza la palabra reservada "function" para declararlas. Es decir, el único cambio que debemos realizar es el de renombrar las operaciones a funciones.
class Foo {
function times2(x) { return x * 2; }
function print(s) { System.out.println(s); }
}
|
Inicialización de atributos
Antes: los valores iniciales de los atributos debían declararse fuera del cuerpo de la clase.
class Foo {
attribute bar: Boolean;
}
attribute Foo.bar = true;
|
Ahora: esto se hace igual que en Java, es decir, dentro de la clase.
class Foo {
attribute bar: Boolean = true;
}
|
Triggers de reemplazo
Antes: los triggers de reemplazo se definían fuera de la clase, utilizando la sintaxis "trigger on atributo = valor"
|
Sin inicialización: class Foo {
attribute bar: Boolean;
}
trigger on Foo.bar = value {
if (bar == true) {
beep();
}
}
Con inicialización:
class Foo {
attribute bar: Boolean = true;
}
trigger on Foo.bar = value {
if (bar == true) {
beep();
}
}
|
Ahora: se definen dentro de la clase, como parte de la declaración del atributo, utilizando la sintaxis "on replace"
|
Sin inicialización: class Foo {
attribute bar: Boolean on replace {
if (bar == true) {
beep();
}
};
}
Con inicialización: class Foo {
attribute bar: Boolean = true on replace {
if (bar == true) {
beep();
}
};
}
|
Cardinalidad
Antes: el operador de cardinalidad era el asterisco ('*').
class Foo {
attribute names :String*;
}
attribute names = ["Monica", "Rachel", "Phoebe"];
|
Ahora: se utilizan en lugar del asterisco, los corchetes ("[]").
class Foo {
attribute names :String[] = ["Monica", "Rachel", "Phoebe"];
}
|
Literales objeto sin atributos
Antes: podíamos referirnos a literales objeto sin atributos utilizando solo el nombre de su clase.
Frame {
title: "Show MenuSeparator"
height: 180
width: 320
menubar: MenuBar {
menus: Menu {
text: "File"
items: [MenuItem {
text: "New"
}, MenuItem {
text: "Open"
}, MenuItem {
text: "Save"
}, MenuSeparator, MenuItem {
text: "Import"
}]
}
}
visible: true
}
|
Ahora: adicionalmente, debemos utilizar llaves ("{}").
Frame {
title: "Show MenuSeparator"
height: 180
width: 320
menubar: MenuBar {
menus: Menu {
text: "File"
items: [MenuItem {
text: "New"
}, MenuItem {
text: "Open"
}, MenuItem {
text: "Save"
}, MenuSeparator {
}, MenuItem {
text: "Import"
}]
}
}
visible: true
}
|
Instancias con nombre
Antes: era posible utilizar algunas instancias con nombre, que representaban constantes predefinidas.
Frame {
title: "White Frame"
background: white
...
}
|
Ahora: es necesario utilizar las constantes predefinidas, o literales objeto.
Frame {
title: "White Frame"
background: Color.WHITE
...
}
O también:
Frame {
title: "White Frame"
background: Color {
red: 1
green: 1
blue: 1
opacity: 1
}
...
}
|
Literales objeto anónimo
Antes: podíamos utilizar literales anónimos y dejar que el interprete infiriese el tipo de ese bloque de código.
...
accelerator: {
modifier: CTRL
keyStroke: O
}
....
|
Ahora: ante la ausencia de interprete, es obligatorio declarar el tipo de cada bloque.
...
accelerator: Accelerator {
modifier: KeyModifier.CTRL
keyStroke: KeyStroke.O
}
...
|
Sobreescribir funciones
Antes: podíamos sobreescribir funciones sin necesidad de colocar el tipo de retorno en la declaración de las mismas.
class MyWidget extends CompositeNode {
...
function composeNode() {
...
}
}
|
Ahora: es obligatorio escribirlo.
class MyWidget extends CompositeNode {
...
function composeNode() :Node {
...
}
}
|
Binding bidireccional
Antes: bastaba con colocar la palabra reservada "bind".
...
TextField {
value: bind model.firstName
}
...
|
Ahora: la sintaxis de JFX Script compilado requiere del uso de la clausula "with inverse".
...
TextField {
value: bind model.firstName with inverse
}
...
|
Casting de Number a Integer
Antes: el casting era automático.
... var real :Number; num = 6.42; var integer :Integer; integer = real; ... |
Ahora: para evitar perdida de precisión en la compilación, debe utilizarse la función "intValue".
... var real :Number; num = 6.42; var integer :Integer = real.intValue(); ... |
Herencia
Al menos hasta la versión del compilador de JavaFX de marzo de 2008, puede que sea necesario utilizar la palabra reservada "as" para evitar algunos problemas de herencia. Es decir, lo que antes hubiesemos hecho de esta forma:
class Foo extends Rectangle {
...
}
...
...
content: Canvas {
content: Foo {
...
}
...
}
...
}
|
Ahora debemos hacerlo así:
class Foo extends Rectangle {
...
}
var foo :Foo = Foo {
...
};
...
content: Canvas {
content: foo as Node
...
}
...
}
|
Bucles
Antes: existían dos bucles, "for" y "foreach".
...
for (Integer i = 0; i < element.length; i++) {
System.out.println(element);
}
...
foreach (element in group) {
System.out.println(element);
}
...
|
Ahora: al igual que con las funciones y operaciones, estos dos conceptos se fusionaron en uno solo que utiliza la palabra reservada "for" en su declaración. Este puede ser utilizado tanto como el "for" de Java así como el "foreach" de JFX Script.
...
for (Integer i = 0; i < element.length; i++) {
System.out.println({element});
}
...
for (element in group where element.length() < 4) {
System.out.println({element});
}
...
|
Si bien esto no fue más que una traducción de la guía de conversión a JFX Script compilado, bastará para que, junto con las partes anteriores de la guía, tengamos una lista mas o menos completa de la sintaxis del lenguaje. A partir de ahora, comenzaremos crear algunas aplicaciones sencillas, para comprender el funcionamiento de las funciones gráficas básicas. Como siempre, les dejo algunos sitios recomendados para visitar mientras voy dándole forma a las próximas partes de este tutorial:
- El blog de James Weaver, en el que este Java Champion nos ofrece ayuda para volvernos un "JavaFXpert". Algunos ejemplos son algo avanzados, pero pueden retroceder hasta los articulos de alrededor de febrero o marzo, en donde los ejemplos son más sencillos y luego avanzar desde allí.
-
Y dos articulos de su autoria: "Creating Rich Internet Applications With Compiled JavaFX Script Technology" y "Using UI Components in Compiled JavaFX Script Technology", ambos bastante básicos y comprensibles.
Nos vemos en la próxima entrega.

Hola Ezequiel soy Emilio. Muy bueno el material, ahora quisiera preguntarte si existe una tabla que relacione los elementos y/o componentes y sus acciones y/o atributos. Espero que se entienda lo que pregunto, creo que esto facilitaría aún mas el desarrollo con JavaFX, por que si bien las sintaxis del JavaFX Script es entendible e intuitivo, falta más info de como relacionar esto, o al menos no la encontré, pero como resumen creo que sería muy importante y más que todo muy consultado cada vez que tengamos que desarrollar en JavaFX.
Enviado por Emilio en agosto 26, 2008 a las 06:08 PM GMT-03:00 #
Emilio, antes que nada, perdón por tomarme 10 días en responderte...
Podes encontrar la referencia del API de JavFX preview 1 en http://javafx.com/releases/preview1/docs/tutorials/apiTables.html o en el menú de ayuda de NetBeans en forma de javadocs.
Espero esto te sirva. Disculpas de nuevo por la tardanza.
Enviado por Ezequiel Aranda en septiembre 06, 2008 a las 07:11 PM GMT-03:00 #