jueves, 18 de septiembre de 2008
Fechas y Calendarios en Java
jueves, 11 de septiembre de 2008
Arrastrar nodos. Objeto evento de ratón.
onMouseClicked(e:MouseEvent){
if (e.getClickCount() == 2) then { ... }
}
HBox/VBox en CustomNode
For/If. Sentencia y Expresión.
lunes, 8 de septiembre de 2008
Diálogos y bloqueos de eventos
jueves, 4 de septiembre de 2008
Segunda Entrega JavaFX. Clases y Objetos
Esta segunda entrega es cortita en extensión, habla del uso de clases y objetos en JavaFX y cómo se relacionan con clases Java. También menciona la particularidad de que las clases JavaFX pueden extender múltiples clases. Quiero dejar en este post también el enlace hacia lo que hasta ahora es la mejor compilación de documentación relativa al compilador y SDK preview de JavaFX. Se trata de un CHM que contiene tanto el API como la referencia más aceptada al lenguaje, así como algunos ejemplos y la documentación relativa al compilador de JavaFX. Se puede encontrar en esta página de GeekyCoder.
Importando Clases
Las sentencias import se comportan de igual modo que en Java. La sintaxis es:
import PackageName.ClassName;import PackageName.*; Si las sentencias import están presentes, deben aparecer antes que cualquier otro código de aplicación (no de la definición package). El lenguaje JavaFX define su propio espacio de trabajo para su librería de clases propias (packages javafx.*), pero las clases de Java también se pueden importar:
import javafx.application.*;import java.lang.System; ... Definiendo Clases
La sintaxis para especificar una clase es la palabra class seguida del nombre de la clase, opcionalmente la palabra clave extends, y una lista separada por comas de las clases base, una llave abierta, una lista de atributos y funciones que acaban todos en punto y coma y una llave cerrada.
JavaFX soporta herencia múltiple y define alguna terminología y reglas nuevas:
- Una clase plana es cualquier clase que extiende directa o indirectamente una clase escrita en Java.
- Una clase de componente es cualquier clase que no es una clase plana.
- Por defecto, las clases escritas en JavaFX son clases de componente.
- Las clases pueden extender, como máximo una clase plana. Si extiende una clase plana, será una clase plana. Una clase puede también extender cualquier número de clases componente o interfaces Java.
Nota: Una clase plana es realmente traducida a una clase Java, mientras que una clase componente es traducida a una clase Java y a una interfaz Java.
Es posible declarar una clase como pública, lo que significa que se puede acceder desde cualquier script. De otro modo, la clase sólo será accesible desde el contenedor del script (esta es la opción por defecto).
JavaFX no soporta constructores, debes usar literales de objeto en su lugar. Para imitar el comportamiento de un constructor, define la función estática que devuelva un nuevo objeto e invoca esa función.
Definiendo Objetos
Como se describió en la anterior entrada, la forma preferible de instanciar una clase es con un objeto literal. Esta forma de emplazamiento de objeto usa una sintaxis declarativa que consiste en el nombre de la clase seguida de una lista delimitada con llaves de inicializadores de atributos. Cada inicializador consiste en el nombre del atributo seguido de una coma, seguida de una expresión que define su valor. Sin embargo, es también posible usar la palabra new cuando se crea un objeto:
import java.io.File; var tmpPath = "/home/users/docs/tmp.txt"var myFile = new File("tmp.txt");(http://javafx.com/releases/preview1/docs/reference/JavaFX-Language.html)
miércoles, 3 de septiembre de 2008
Clientes WebService con NetBeans 6.1
lunes, 1 de septiembre de 2008
Funcionamiento de menú con JavaFX.
La clase nodo contiene un rectángulo con relleno de color aleatorio, un texto y además una variable timeline para el efecto de "aparecer".
/*
* una.fx
*
* Created on 22-sep-2008, 10:58:54
*/
package com.megestiono.widgets;
/**
* @author Alvaro
*/
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.Font;
import javafx.scene.FontStyle;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
public class Nodo extends CustomNode {
public attribute texto:String="N/A";
attribute opa:Number=0;
public attribute t = Timeline {
repeatCount: 1
keyFrames : [
KeyFrame {
time : 1s
values : [
opa => 1 tween Interpolator.LINEAR
]
}
]
}
public function aparece():Void{
t.start();
}
public function create(): Node {
var rnd = new java.util.Random();
return Group {
opacity: bind opa
content: [Rectangle {
x: 0, y: 0
width: 200, height: 200
fill: Color.rgb(rnd.nextInt(255),rnd.nextInt(255),rnd.nextInt(255))
},Text {
font: Font {
size: 20
style: FontStyle.PLAIN
}
x: 10, y: 40
content: texto
}]
};
}
}
Nodo {texto:"UnTexto"}
//La ventana desde donde los gestiono con un menú rudimentario construido con rectángulos.
import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.layout.*;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.*;
import javafx.application.WindowStyle;
var secuencia1:String[] = ["Uno","Dos","Tres"];
var secuencia2:String[] = ["Cuatro","Cinco","Seis"];
var arraynodos1:Nodo[] = [Nodo{texto:secuencia1[0]},Nodo{texto:secuencia1[1]},Nodo{texto:secuencia1[2]}];
var arraynodos2:Nodo[] = [Nodo{texto:secuencia2[0]},Nodo{texto:secuencia2[1]},Nodo{texto:secuencia2[2]}];
var nodos:Nodo[] = arraynodos1;
Frame {
title: "Menus"
width: 300
height: 300
closeAction: function() {
java.lang.System.exit( 0 );
}
visible: true
windowStyle: WindowStyle.TRANSPARENT
stage: Stage {
content: [VBox{
spacing:10
content:[HBox{
spacing:10
content:[Rectangle {
x: 0, y: 0
width: 50, height: 30
fill: Color.FORESTGREEN
onMousePressed: function (e){
for (nodo in nodos){
nodo.visible = false
}
nodos
[0].visible = true;
nodos
[0].t.start();
}
}, Rectangle {
x: 0, y: 0
width: 50, height: 30
fill: Color.FORESTGREEN
onMousePressed: function (e){
for (nodo in nodos){
nodo.visible = false
}
nodos
[1].visible = true;
nodos
[1].t.start();
}
}, Rectangle {
x: 0, y: 0
width: 50, height: 30
fill: Color.FORESTGREEN
onMousePressed: function (e){
for (nodo in nodos){
nodo.visible = false
}
nodos
[2].visible = true;
nodos
[2].t.start();
}
}, Rectangle {
x: 0, y: 0
width: 50, height: 30
fill: Color.RED
onMousePressed: function (e){
if (nodos == arraynodos2){
nodos = arraynodos1;
nodos
[0].visible = true;
nodos
[0].t.start();
} else {
nodos = arraynodos2;
nodos
[0].visible = true;
nodos
[0].t.start();
}
}
}]
}
,
Group{
content:bind nodos
},
Rectangle {
x: 270, y: 20
width: 50, height: 50
fill: Color.BLACK
onMouseClicked: function (e){
java.lang.System.exit( 0 );
}
}
]
}
]
}
}
jueves, 14 de agosto de 2008
Primera Entrega JavaFX. Generalidades del Lenguaje
Esta primera entrada proporciona una vista general del lenguaje JavaFX Script. Describe sus funcionalidades principales, dejando los detalles para capítulos siguientes. Este documento está orientado a diseñadores y desarrolladores de aplicaciones ricas de cliente en Internet RIA, que funcionan en páginas web, como el software Java Web Start o como aplicaciones tradicionales de escritorio. Su contenido asume que el lector está familiarizado con el lenguaje Java.
El lenguaje de programación JavaFX Script tiene las siguientes particularidades:
- Usa sintaxis declarativa para especificar componentes GUI, habilitando al código del desarrollador acercarse al diseño real del GUI.
- Usa enlazado de datos declarativos y evaluación incremental, permitiendo la creación y configuración sencilla de componentes individuales. Los datos de aplicación y los componentes GUI se sincronizan automáticamente.
- Está tipado estáticamente, teniendo la mayor parte de estructuración de código, reuso y encapsulación que permiten la creación y mantenimiento de programas muy grandes en el lenguaje Java.
- Funciona con la mayoría de IDES, incluyendo NetBeans.
- Es capaz de soportar GUIs de cualquier tamaño y complejidad
- Es más sencillo de utilizar que Swing.
Scripts
En el lenguaje JavaFX, un script es una o más declaraciones de expresiones. Evaluando el script se evalúan las declaraciones o expresiones en orden:
var ten : Integer = 10;
java.lang.System.out.println("Twice {ten} is {2 * ten}.");
Esto muestra:
Twice 10 is 20.
A diferencia de una aplicación escrita en Java, un script no necesita contener ninguna definición de clase ni funciones.
Clases
Las definiciones de clases comparten muchas similitudes con Java, pero algunas diferencias son notables. El estado, por ejemplo, es información almacenada en atributos, no en campos. El comportamiento se expone a través de funciones y no métodos (más adelante se verá que ha desaparecido "operation" en la nueva versión del lenguaje, ahora se utiliza "function" tanto para métodos, no usando "return", como para funciones, con "return"). El siguiente ejemplo define una clase simple Rectangle que muestra la sintaxis básica de cada uno.
class Rectangle {
attribute width: Integer;
attribute height: Integer;
function grow(): Void {
grow(1);
}
function grow(amount: Integer): Void {
width += amount;
height += amount;
}
}
El lenguaje de programación soporta herencia múltiple, haciendo posible que una clase herede de más de una clase.
Objetos
Objetct literals proporciona una sintaxis simple para instanciación de clase. El siguiente código crea una única instancia de la clase Rectangle definida previamente, inicializando sus atributos width y height a 100. (Nótese que no se necesita new)
Rectangle {
width: 100
height: 100
}
Para guardar una referencia a este objeto, usa la palabra var:
var myRect = Rectangle {
width: 100
height: 100
}
Expresiones y Operadores
Como cualquier otro lenguaje de programación, el lenguaje JavaFX Script soporta expresiones y operadores.
El capítulo 5 discute las expresiones y operadores disponibles en el lenguaje JavaFX Script.
Secuencias
Una secuencia guarda una lista ordenada de objetos. Esto es análogo grosso modo a los arrays de Java. Ambos guardan múltiples valores y son accedidos por un índice comenzando por 0.
var week = ["Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday"];
var mon = week[0];
var wed = week[2];
var fri = week[4];
También están soportadas las porciones (slice) de secuencias:
var week = ["Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday"];
var weekdays = week[0..4]; // first slice
var weekend = week[5..6]; // second slice
Enlazado de Datos (bind)
El enlazado de datos proporciona una sintaxis simple para sincronizar el estado de objetos múltiples. Cuando dos objetos están enlazados uno con el otro, el valor del segundo objeto cambia automáticamente cuando el primero se actualiza. Un uso común de enlazado de datos es guardar componentes GUI sincronizados con sus datos por debajo.
import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.text.Text;
var myString = "Hello World!";
Frame {
width: 50
height: 50
visible: true
stage: Stage {
content: Text {
content: bind myString
}
}
}
// Si otra parte del código cambia myString
//el texto del GUI cambiará automáticamente
Disparadores (Triggers)
Los disparadores (triggers) son bloques de código que se ejecutan cuando se satisfacen ciertas condiciones. Por ejemplo, puede que quieras estar alertado de si el valor de un atributo ha sido establecido a algo que no es apropiado. El siguiente ejemplo muestra la sintaxis básica de un trigger:
import java.lang.System;
ReplaceDemo {
mySensitiveData: "Will anyone notice?"
}
class ReplaceDemo {
attribute mySensitiveData: String
on replace {
System.out.println("I noticed a change!");
};
// application-specific safeguarding code would go here
}
miércoles, 13 de agosto de 2008
Dudas para el "Ask the Expert" del día 18
Q: Aplicación de efectos. Máscaras? InvertMask {input: effect}. Desaparición de método clip de los elementos gráficos en el api del sdk preview.
martes, 12 de agosto de 2008
Scene Graph & JWebPan
Además en este documento se habla de JWebPane que permite la renderización de código HTML con CSS y JavaScript, algo de lo que ya sabíamos y de lo que no había vuelto a leer nada sobre ello para el preview sdk.
Veo muchas más cosas interesantes sobre JavaFX en la página de JavaOne. Voy a estar entretenido un rato.
Id de Nodo
Teniendo en cuenta que cuando se añade un grupo que contiene distintos nodos (que serán las pantallas que queramos ver), se van a superponer uno sobre otro, únicamente habrá que posicionar el grupo en la pantalla principal y gestionar el atributo de visibilidad de cada uno.
Con la propiedad nodo se me ocurre tener alguna funcionalidad más. A la hora de crear los botones del menú, podría plantearme pasar únicamente el id como parámetro de creación y que sea el objeto botón el que se preocupe de construir sus recursos. Esto me obligaría a tener controlados los nombres de los ficheros de imágenes.
jueves, 7 de agosto de 2008
JavaFX SDK Preview
En breve, subiré los ejemplos con los que estoy trabajando. Construcción de botones con comportamientos, distribuciones de nodos para formar el diseño en pantalla, animaciones con máscaras. También aprovecharé para subir la documentación que he traducido y comentaré algunos cambios curiosos que ha tenido el lenguaje.
martes, 5 de agosto de 2008
Esquemas de Diseño en Pantalla
Es aquí donde veo que existen dos clases llamadas VBox y HBox en el paquete javafx.scene.layout (VerticalBox y HorizontalBox, supongo) que se pueden usar para establecer la disposición de los nodos que se muestren en pantalla. He comprobado que efectivamente, son nodos los que toman estas clases como argumentos de su contenido y por ende todos los objetos de las clases que implemento como hijos de CustomNode son perfectamente añadibles. El funcionamiento de las dos clases parece idéntico excepto, claro está, que una dispone sus nodos de forma vertical y otra horizontal. Supongo que se podrán tomar cada una de ellas como nodos de su contenido de forma que se puedan arreglar disposiciones más complejas. He comprobado que efectivamente son anidables, con estas disposiciones se pueden acomodar distintos diseños en pantalla. Desconozco si ésta es la forma en la que se quiere que los desarrolladores hagan la distribución de objetos en pantalla o no.
De acuerdo, podemos hacer diseños con menús de botones que diseñamos previamente. Podemos Interactuar entre objetos mostrados en pantalla. Mi pregunta es ahora, ¿cómo puedo cargar y descargar objetos de una zona en concreto?. Mi idea es poder definir una jerarquía de contenidos en los que los menús definen los objetos mostrados.
Leyendo un manual de ActionScript 2 veo que tiene dos funciones con ciertas similitudes que se llaman HBox y VBox y que realizan una función muy similar. Da que sospechar.
Perfilador de SceneGraph
http://www.nobel-joergensen.com/roller/java/entry/profiling_javafx_rendering
veo que la aplicación que nos propone funciona mucho mejor. ¿Pero y el resto de las aplicaciones que ya tengamos funcionando? ¿puede ser esta la causa de que no tenga buen comportamiento mi botón negro?
¿Qué es SceneGraph?, ¿qué tiene que ver con todo ésto?. Esta tecnología se ha incorporado al API de JavaFX recientemente. SceneGraph no sólo se utiliza con JavaFX, también se utiliza con Swing.
Anodino
Creo que ya tengo resuelta esa duda. Cuando se llaman a clases desde un frame, se accede a la última clase compilada. Aunque el visor de dentro de NetBeans muestre la clase ya compilada, no es ésa la que está en el paquete que después es llamada. Hay que refrescar las clases disponibles (F11).
- Ejemplo de botón negro, el triángulo
- Ejemplo de BlurMotion
- Tengo una distribución de botones que no actualizan lo mostrado al código que ... Hay algunas clases que no refrescan su clase compilada después de construir el proyecto.
- La url que tiene como argumento la clase image debe tener especificar el protocolo en su ruta. De esto me he dado cuenta cuando he visto que las urls externas "http://..." funcionaban sin mayor problema pero ha sido cuando he especificado una ruta como esta: "file:///c:/Documents%20and%20Settings/alvaro.EUROPA-SYSTEM/Mis%20documentos/NetBeansProjects/JFXSandBox/img/mensajes.png" cuando por fin ha podido leer el fichero en la máquina local. No sólo se trata del "file:///" al principio sino que no admite espacios en medio tampoco.
Anodino y Edificante JFX
De este código, una vez visto correr, se pueden inferir reglas interesantes. El código del script es el siguiente:
import javafx.ext.swing.*;
import javafx.scene.geometry.*;
import javafx.scene.paint.*;
import javafx.animation.*;
import java.lang.System;
var x = 0;
var t = Timeline { // Utilizo Timeline como un objeto al que le aplicaré
repeatCount: 3 // los métodos start() y stop(). Interesante atributos
autoReverse: true // repeatCount y autoReverse
// Únicamente modifico el valor de x que es accesible
// dentro del script. Es a este valor al que se hace
// referencia con un bind del atributo animable
// La estructura general de Timeline es metódica
keyFrames: [KeyFrame{time : 0s
values: x => 0},
KeyFrame{time : 2s
values: x => 400 tween Interpolator.LINEAR}
]//keyFrames
}//Timeline;
SwingFrame {
closeAction: function(): Void {System.exit(0);}
title : 'Animation: Simple'
background : Color.WHITE;
width : 550
visible : true
content: BorderPanel{
top: Canvas {content:
Rectangle {x : bind x
y : 0
width : 100
height: 100
fill : Color.BLUE
}
}//Canvas
bottom: FlowPanel{content: [ // La versión de compilación de la que
// dispongo no utiliza SwingButton sino
// Button (igualmente tiene atributo action)
Button{text : "Start"
action: function(): Void{t.start();}},
Button{text : "Pause"
action: function(): Void{t.pause();}},
Button{text : "Resume"
action: function(): Void{t.resume();}},
Button{text : "Stop"
action: function(): Void{t.stop();}}
]}//FlowPanel
}//BorderPanel
}//SwingFrame
La animación siempre hace uso de la función especial (de JavaFX, también la he visto en Swing) bind. Esta tiene la propiedad de actualizar automáticamente el valor del atributo al que se le asocia cuando cambia el valor de una variable y es ésta variable primera la que cambia con el tiempo con el objeto Timeline.
El tema con el sizeof me mola.
JavaFX permite hacer comparaciones de cadenas con el operador lógico "==" que se utiliza para comprobar igualdad entre cualquier tipo de variables. Esto es una diferencia con el lenguaje Java que necesita del método .equals().
JavaFX
Será en este blog donde recoja las conclusiones, observaciones e impresiones sobre mi toma de contacto con esta tecnología.