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

miércoles, 21 de enero de 2009

JavaFX: Pintando un array (arreglo) de funciones y detectando el mouse encima


En este ejercicio es posible descubrir varias cosas interesantes:

1) Como se puede crear un arreglo cuyos elementos son funciones que retornan figuras gráficas.

2) Como se pueden consolidar en una sola figura los resultados de las funciones en el arreglo (bind for....)

3) Como, sin hacer nada adicional, el programa es capaz de detectar cuando el mouse entra y sale de esta figura consolidada.

4) Finalmente, como detalle gráfico, muestra como se puede aplicar un efecto de sombra sobre la figura consolidada.


Bastante para tan poco código, ¿no?





package experimentfunctions;

import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.scene.effect.*;
import javafx.animation.Timeline;

var count:Integer=0;

function circulo():Circle {
Circle{
radius:90
fill:Color.RED
}
};

function rectangulo():Rectangle {
Rectangle{
width:100
height:75
fill:Color.BLUE
}
};

function texto():Text {
Text{
translateX: -80
translateY: -70
font: Font{
name:"Verdana"
embolden:true;
size:24
}
content: "Prueba de texto"
}
};

var functions=[
circulo(),
rectangulo(),
texto()
];

var shadow=0;

var shadowAnim = Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at(0s) { shadow => 4 }
at(0.3s) { shadow => 10}
]
};

Stage {
title: "Application title"
width: 250
height: 250
scene: Scene {
content: Group {
translateX:100
translateY:100
content: bind for (shape in functions) shape;
effect: DropShadow {
offsetY: bind shadow
offsetX: bind shadow
}
onMouseEntered: function(e) {
shadowAnim.stop();
}
onMouseExited: function(e) {
shadowAnim.play();
}
}
}
}

shadowAnim.play();

Una explicación más detallada sobre bind for (shape in functions) shape.

Lo que hace esta instrucción es... obtener cada una de las funciones en el arreglo:

for (shape in functions)

... luego ejecutarlas y pasar ese resultado como parte del contenido a pintar.

Una forma más ordenada de presentar el código sería:

content:
bind
for (shape in functions)
shape; <-- ejecuta y retorna la figura

lunes, 19 de enero de 2009

JavaFX: Bind with inverse. Ajusta tamaño de círculo a tamaño de la ventana


La instrucción BIND es una de las cosas interesantes de JavaFX Script. Esta permite declarar la DEPENDENCIA entre una variable y otros elementos del programa. Por ejemplo, si al declarar un circulo, se define que el color de este dependerá de una variable X, al cambiar el color asignado a X se produce la actualización automática del círculo en pantalla, sin necesidad de ordenar al programa que repinte.




Circle {
radius:20
fill:bind colorcirculo
}

Ahora bien, la instrucción BIND puede ir acompañada de la instrucción WITH INVERSE, por ejemplo:

var a=bind b with inverse;

Esto significa que cuando se cambie el valor de 'b' en algún lugar del programa, se asignará el nuevo valor de 'b' a 'a', pero también quiere decir que cuando se modifique el valor de 'a' también se traspasará el valor de 'a' a 'b'.

¿Qué utilidad puede tener esta instrucción? ... pues, por ejemplo, se puede usar para ajustar el tamaño de un círculo al tamaño de la ventana que lo contiene... o para conocer las medidas de la ventana y cuando se cambia su tamaño.

En el siguiente ejemplo, se usa 'bind with inverse' para asignar el tamaño inicial de la ventana (300x300 pixeles)... pero luego, cuando se ajusta manualmente el tamaño de la ventana, la misma instrucción 'bind with inverse' pasa de regreso el tamaño actualizado de la ventana a las variables 'h' y 'w' que originalmente definieron su tamaño (h=height=alto y w=width=ancho).


package experimentsize;

import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import java.lang.System;

// tamaño inicial de la ventana
var w=300.0 on replace {
println("ajusto ancho de la ventana a {w}");
};
var h=300.0 on replace {
println("ajusto alto de la ventana a {h}");
};

// borde horizontal de la ventana
var bh=16.0;
// borde vertical de la ventana (incluye titulo)
var bv=36.0;

Stage {
title: "Ajusta al tamaño de ventana"
width: bind w with inverse
height: bind h with inverse
scene: Scene {
content: {
Circle {
translateX: bind (w - bh) / 2
translateY: bind (h - bv) / 2
radius:bind
if (w < h) then (w - 50) / 2 else ( h - 80) / 2
fill:Color.RED
}
}
}
}

sábado, 17 de enero de 2009

JavaFX: Clases de clases... y dos Scene alternadas


Este ejemplo crea una clase que hace rotar un círculo. Luego, crea una nueva clase que utiliza varias instancias de la primera clase para hacer rotar varios círculos dentro del nuevo objeto. Finalmente, crea varias instancias de este último tipo de objeto y los pone en dos Scene que luego alterna... es decir, es un Stage con dos Scene.




package experimentroam;

import javafx.stage.Stage;
import javafx.animation.*;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;

// clase basica que dibuja circulo moviendose formando un cuadrado
class myObject extends CustomNode {

var x:Number;
var y:Number;

public var ix=0;
public var iy=0;
public var dx=100;
public var dy=100;
public var radius=40;
public var color=Color.RED;

var roamingtimeline = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
at(0s) { x => ix+radius; y => iy+radius }
at(0.3s) { x => dx-radius; y => iy+radius }
at(0.6s) { x => dx-radius; y => dy-radius }
at(0.9s) { x => ix+radius; y => dy-radius }
at(1.2s) { x => ix+radius; y => iy+radius }
]
};

// mensaje desplegado (compuesto por texto y rectangulo a su alrededor)
override protected function create():Node {
roamingtimeline.play();
Group {
content: [
Circle {
centerX: bind x
centerY: bind y
radius: bind radius
fill: bind color
}
]
}
};

};


// clase compuesta por objetos de la clase precedente
class myBigObject extends CustomNode {

var fig:myObject=myObject{
ix: 0
iy: 0
radius:55
dx:250
dy:250
color:Color.PURPLE
}
var fig2:myObject=myObject{
ix: 40
iy: 40
radius:40
dx:210
dy:210
color:Color.RED
}
var fig3:myObject=myObject{
ix: 80
iy: 80
radius:30
dx:170
dy:170
color:Color.GREEN
}
var fig4:myObject=myObject{
ix: 120
iy: 120
radius:20
dx:130
dy:130
color:Color.BLUE
}
var fig5:myObject=myObject{
ix: 160
iy: 160
radius:10
dx:90
dy:90
color:Color.YELLOW
}
var fig6:myObject=myObject{
ix: 190
iy: 190
radius:5
dx:60
dy:60
color:Color.ORANGE
}

override protected function create():Node {
Group {
content: [
fig,
fig2,
fig3,
fig4,
fig5,
fig6
]
}
};

}


// instancia de clase compuesta
var bigFig:myBigObject=myBigObject{};

// instancia de clase compuesta desplazada en la pantalla
var bigFig2:myBigObject=myBigObject{
translateX:250
translateY:0
};
// instancia de clase compuesta desplazada en la pantalla
var bigFig3:myBigObject=myBigObject{
translateX:250
translateY:250
};
// instancia de clase compuesta desplazada en la pantalla
var bigFig4:myBigObject=myBigObject{
translateX:0
translateY:250
};

var myScene:Scene=Scene {
fill:Color.BLACK
content: [
bigFig,
bigFig2,
bigFig3,
bigFig4
]
};

var myScene2:Scene=Scene {
fill:Color.BLACK
content: [
bigFig,
bigFig3,
]
};

var scenes=[myScene, myScene2];
var activeScene:Integer;

Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
at(0s) { activeScene => 0 }
at(1s) { activeScene => 1 }
]
}.play();

Stage {
title: "Application title"
width: 500+16
height: 500+36
scene: bind scenes[activeScene]
}