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:

Nos vemos en la próxima entrega.

Comentarios:

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 #

Enviar un comentario:
  • Sintaxis HTML: Deshabilitado

This blog copyright 2009 by Ezequiel Singer