Mostrando entradas con la etiqueta codigo. Mostrar todas las entradas
Mostrando entradas con la etiqueta codigo. Mostrar todas las entradas

viernes, 5 de junio de 2009

JavaFX 1.2 incluye APIs para gráficos (charts)


Este es el código para agregar un gráfico de Pie en JavaFX

package piechartsample;

import javafx.scene.chart.*;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;

var name = ["Java", "JavaFX", "MySQL", "Netbeans", "Others"];
var val = [20, 12, 25, 22, 30];


var r : PieChart.Data[] = [];
for(i in [0..4]) {
insert PieChart.Data {
action: function() {
print("Name :: {name[i]}");
}
label : name[i] value : val[i] } into r; }


var chart = PieChart3D {
data : r
pieLabelFont: Font.font("dialog", FontWeight.REGULAR, 8);
pieLabelVisible: true
pieValueVisible: true
pieToLabelLineOneLength: 3
pieToLabelLineTwoLength : 6

}

var st = Stage {
height: 420
width: 480
title:"Pie Chart 3D"
scene: Scene {
content: [
chart
]
}
}

Este es el código para un gráfico de "burbujas":


package bubblechart;

import javafx.scene.chart.*;
import javafx.scene.chart.part.*;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
var x: Number[] = [30, 60, 10, 100,50];
var y: Number[] = [40,20,90,40,23];
var radius: Number[] = [10,13,7,10,5];

var x1: Number[] = [13, 20, 100, 30,50];
var y1: Number[] = [100,80,60,40,20];
var radius1: Number[] = [7,13,10,6,12];

var r : BubbleChart.Data[] = [];
var r1: BubbleChart.Data[] = [];
for(i in [0..4]) {
insert BubbleChart.Data {fill: Color.YELLOWGREEN xValue : x[i] yValue : y[i] radius: radius[i] }into r;
insert BubbleChart.Data {fill: Color.RED xValue : x1[i] yValue : y1[i] radius: radius1[i] }into r1;

}
var s1 : BubbleChart.Series = BubbleChart.Series{data: [r,r1]};
var BubbleChartData : BubbleChart.Series[] = [s1];
var chart = BubbleChart {
title : "BubbleChart"
xAxis : NumberAxis{
lowerBound: 0
upperBound : 150
label: "SomeX"
visible: true
axisStrokeWidth: 1
tickUnit : 20
tickLabelsVisible: true

}
yAxis : NumberAxis{
lowerBound: 0
upperBound : 150
tickUnit: 20
label: "SomeY"
visible: true
tickLabelsVisible: true
}
data : BubbleChartData
}

var st = Stage {
height: 520
width: 640
title:"Bubble Chart"
scene: Scene {
content: [
chart
]
}
}


domingo, 12 de abril de 2009

"On Replace" no es "On Modify"...


No tengo claro si hay alguna manera de hacer que "on replace" se dispare al modificar una variable de una clase definida por el usuario (supongo que no, porque se llamaría ON MODIFY). Al parecer es necesario recrear el objeto y asignarlo a la variable para que "on replace" detecte el cambio.

Digamos que defino una clase:

public class Data {
public var attrib1:Number=0.0;
public var attrib2:String="";
}

Luego, creo una instancia de la clase:

var data1:Data = Data {
attrib1: 1.2,
attrib2: "Mauricio"
} on replace {
println("{data1.attrib1} {data1.attrib2}");
};
data1.attrib2="Omar";
data1.attrib2="Veronica";

La salida de este ejemplo es:

1.2 Mauricio

Es decir, al asignar "Omar" o "Veronica" a attrib2, el bloque "on replace" de data1 no se dispara.

La única manera (que conozco) de evitar esto es asignar una nueva instancia del objeto a data1:

data1= Data { attrib1:data1.attrib1 attrib2:"Omar"};

Quizás haya alguna forma de declarar la variable con algún tipo de binding o algo por el estilo que permita detectar los cambios de variables dentro de una instancia.

Por ahora, vale la pena tener este detalle presente para evitar problemas y pérdidas de tiempo... si uno no lo sabe, puede no ser evidente que esa parte del código no se está ejecutando y hay un bug en el código.

jueves, 12 de febrero de 2009

JavaFX: Stage "controller" demo - Demo "controlador" de Stage


This small code demostrates how easy is to handle the onResize and onMove events implemented by the Stage controller (Stage Controller).

Este pequeño código demuestra lo fácil que es manejar los eventos onResize y onMove implementados por el controlador de Stage (Controlador de Stage)



Here's the code / Aquí está el código:

var img = Image { url: "{__DIR__}myimage.jpg" };
var rect:Rectangle;
var sw:Integer;
var sh:Integer;

var cs = controlStage {
timeToCallFunctions:0.001s
timeToCheckPosSize:0.001s
initialPosition:controlStage.CENTER, persist:true
checkMinWidth:true, minWidth:270,
checkMinHeight:true, minHeight:270,
stickyBorders:true
onResize: function(e) { clip(e) }
onMove: function(e) { clip(e) }
};

// screen resolution
sw = cs.maxScrWidth;
sh = cs.maxScrHeight;

function clip(r:Rectangle2D) {
rect = Rectangle {
x: r.minX - (sw - img.width) / 2
y: r.minY - (sh - img.height) /2
width: r.width, height: r.height
}
};

Stage {
width: bind cs.width with inverse
height: bind cs.height with inverse
x: bind cs.x with inverse
y: bind cs.y with inverse
onClose: function() { cs.persistStage() };

scene: Scene { content:
ImageView {
translateX: bind -rect.x
translateY: bind -rect.y
image: img
clip: rect
}
}
};



Download the Netbeans 6.5 project, here. Descarga el proyecto Netbeans 6.5, aquí.

miércoles, 4 de febrero de 2009

JavaFX: un detalle importante sobre como se retornan valores


Si se han fijado, muchas veces nos encontramos con cosas como esta en el código de una aplicación JavaFX:

function figura():Node {
Group {
content: Line { startX:0,
startY:0, endX:100,
endY:100 }
}
};


Ahora, según la definición de la función, esta debe retornar un NODO (un objeto que puede ser una figura geométrica o una imagen, por ejemplo). Pero ese código, nunca ejecuta "explícitamente" un return.

Lo que sucede, es que JavaFX Script asume (salvo que exista explícitamente una instrucción RETURN), que la última expresión evaluada es lo que se retorna. En el caso del código (arriba), retornaría el Group.

El código escrito de manera más "formal" podría ser este:

function figura():Node {
var objeto = Group {
content: Line { startX:0,
startY:0, endX:100,
endY:100 }
};
return objeto;
};


Ahora, esta flexibilidad no deja de tener su encanto al poder por ejemplo escribir algo como:

var resultado:Number = if (a==b)
then { a+b/c } else { d/e+f };


... o poder decribir el cuerpo de una función como:

function calculo(a:Number,
b:Number):Number {

a + 1000 / b

};


En realidad, es un detalle que no deja de ser comodo y que hace más comprensible y breve el código... quizas más natural (siendo siempre opcional, y teniendo siempre la posibilidad de ser mas "formal" al codificar).

Ojalá esta explicación ayude a que comprendan mejor el código de algunos scripts.

JavaFX: a Knob control - Un control "de perilla"


Update: Stage Controller hosted on Google Code, includes documentation for using the class. Click Here for a Java Web Start example.

English: Please, visit the Google Code hosted project

JavaFX me está convirtiendo realmente en una fábrica de componentes... este control lo desarrollé en menos de un día. Como verán es bastante sofisticado. No voy a entrar en detalles por ahora, pero el código del programa de ejemplo explota varias de sus funcionalidades.



Una de las cosas que dejo pendiente de demostrar, es cómo se pueden agregar nuevos tipos de perillas... basta con crear la gráfica en Adobe Illustrator y luego crear una clase que herede de la clase basicKnob (update: ver orangeKnob.fx). En esa nueva clase, pueden incluir detalles propios de la gráfica asociada... entre otras cosas, el nombre del archivo que contiene la grafica, las dimensiones de la nueva perilla (ancho y alto) y el radio inicial y final de las lineas del dial (la distancia al radio de la perilla), de manera que el componente pueda dibujar las lineas que le solicite el usuario y que estas lineas coincidan con la gráfica importada (update: ahora también incluye el radio inicial y final de las líneas cortas en el dial).

Aquí va el código fuente del componente, el programa demostrativo, los archivos de gráficos, etc. Sólo tienen que abrirlo en Netbeans 6.5 y ejecutarlo ;D

¡Ah! un detalle que me dió dolor de cabeza, hasta que recordé que lo había leído antes... si se fijan en el código, por cada control instancio la gráfica de la perilla ( ui: orangeKnob{} )... esto es así, porque si creo una sóla instancia y luego la enlazo desde varios lugares, solo queda activo el último enlace.... quizás debería ver si se puede crear algo como una versión "estática" con la gráfica... pero eso tengo que investigarlo y luego probar si funciona.

Descarga el proyecto completo de Netbeans 6.5... Download the complete Netbeans project... CLICK HERE.

miércoles, 28 de enero de 2009

Mi primer juego en JavaFX: Alunizaje


Al juego le falta un par de detalles, como que la nave aparezca inicialmente en cualquier area de la pantalla. Por ahora aparece al centro a una velocidad y dirección aleatoria. También me falta agregar que la "base" de alunizaje tenga una posición aleatoria y que detecte cuando aterriza fuera de ella. Son detalles menores que quizas hasta puedes terminar tú.



El juego usa 4 teclas. La barra de espacio, para encender el motor principal. Las teclas de flecha hacia izquierda y derecha, que encienden los motos auxiliares para inclinar el módulo, y la tecla con la flecha hacia arriba, que enciende el piloto automático, para frenar la rotación del módulo (automáticamente).

Está bastante realista, los retrocohetes se encienden cuando corresponde y dejan de operar cuando no hay mas combustible. También incluye alarmas visuales y sonoras para cuando se excede la velocidad de aterrizaje, la inclinación del módulo es incorrecta cuando esta cerca de alunizar o cuando el combustible baja de 1/3 del estanque.

Me resultó entretenido hacer este juego y también descubrir LO INCREIBLEMENTE SIMPLE que es desarrollar cosas bastante decentes en tan poco tiempo (el grueso estaba operando en un par de horas... ¡y eso que estoy aprendiendo JavaFX script!).

La facilidad de incluir gráficos desde Adobe Illustrator sin duda es una ventaja inmensa. Especialmente, porque puede ser reemplazada por el trabajo de un diseñador más experto, sin necesidad de tocar el código de JavaFX script ya desarrollado. De hecho, con poco trabajo adicional podría agregarse multiples "skins" o apariencias al juego... escenarios de distintos planetas y naves por ejemplo (pudiendo relocalizar las alarmas, botones, formas de la nave, motores, entorno, etc).

El proyecto Netbeans 6.5 completo está disponible aquí (código fuente, gráfica, sonidos, etc).

El código requiere que esté incluida la libreria JavaFX FXD 1.0 en el proyecto.

sábado, 6 de diciembre de 2008

JavaFX: La rueda de la fortuna


Este ejemplo genera una "rueda" de colores de distinta intensidad y que gira... el ejemplo original viene incluido con Netbeans 6.5, yo sólo le agregué el giro. Pueden modificar la velocidad del giro cambiando el tiempo en el Timeline (0.5s, o medio segundo para una vuelta completa).

Básicamente, lo único que agregué fue un rotate: bind angle; asociado a la rueda ya generada incluida en la escena (Scene) y una "linea de tiempo" (Timeline) que incrementa el ángulo entre 0º y 360º, en el tiempo especificado. Una vez que llega a 360º, comienza por el ángulo 0º. Así queda la impresión que la ruega gira indefinidamente.



package color;

import javafx.scene.Group;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.Timeline;
import javafx.lang.FX;

class ColorWheelNode extends CustomNode {

var segments : Number = 12;
var steps : Number = 6;
var radius : Number = 95;
var stripes : Arc[];

override function create() : Node {
return Group {
content: bind stripes
};
}

init {
// Set radius
var r = radius;
var rStep = radius / steps;
var colors : Color[];
for( i in [1..
segments + 1] ) {
insert Color.rgb( 255, 255, 0 ) into colors;
}
for( i in [0..
steps - 1] ) {
colors[1] = Color.rgb( 255 - ( 255 / steps * i ), 255 - ( 255 / steps * i ), 0 );
colors[2] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 1.5 ) - (( 255 / 1.5 ) / steps ) * i, 0 );
colors[3] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 2 ) - ( ( 255 / 2 ) / steps ) * i, 0 );
colors[4] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 2.5 ) - (( 255 / 2.5 ) / steps ) * i, 0 );
colors[5] = Color.rgb( 255 - ( 255 / steps ) * i, 0, 0 );
colors[6] = Color.rgb( 255 - ( 255 / steps ) * i, 0, ( 255 / 2 ) - (( 255 / 2 ) / steps ) * i );
colors[7] = Color.rgb( 255 - ( 255 / steps ) * i, 0, 255 - ( 255 / steps ) * i );
colors[8] = Color.rgb(( 255 / 2 ) - (( 255 / 2 ) / steps ) * i, 0, 255 - ( 255 / steps ) * i );
colors[9] = Color.rgb( 0, 0, 255 - ( 255 / steps ) * i );
colors[10] = Color.rgb( 0, 255 - ( 255 / steps ) * i, ( 255 / 2.5 ) - (( 255 / 2.5 ) / steps ) * i );
colors[11] = Color.rgb( 0 , 255 - ( 255 / steps ) * i, 0 );
colors[12] = Color.rgb(( 255 / 2 ) - (( 255 / 2 ) / steps ) * i, 255 - ( 255 / steps ) * i, 0 );
for( j in [1..segments] ) {
var c = colors[
j.intValue()];
insert Arc {
centerX: 100,
centerY: 100
radiusX: r ,
radiusY: r
startAngle: 360 / segments * ( segments - j - 0.5)
length: 360 / segments
fill: c
type: ArcType.ROUND
} into stripes;
}
r -= rStep;
}
}
}


var angle:Integer;

Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: false
keyFrames: [
at (0s) {angle => 0},
at (0.5s) {angle => 360},
]
}.play();



Stage {
scene: Scene {
fill: Color.GRAY
content: ColorWheelNode {
rotate: bind angle;
}
}

width: 216
height: 232
title: "Color Wheel"
}