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

lunes, 16 de marzo de 2009

Agregando funcionalidad a eventos, sobre la marcha


Mientras desarrollaba el componente de menú flotante, me encontré con esta posibilidad... agregar funcionalidad a un evento... sobre la marcha.

El asunto es este. Si defino un evento onMousePressed de un círculo, ¿como podría agregar funcionalidad a ese evento sin alterar el código y sin crear un nuevo tipo de clase?

Entonces pense... ¿qué tal si primero obtengo la funcionalidad en un evento (onMousePressed) de un objeto y la guardo en una variable? ... Luego, ¿qué tal si reemplazo el evento onMousePressed de ese objeto, con una nueva función en la que primero ejecute la funcion original (guardada en la variable) y luego agrego la nueva funcionalidad?

Bueno, es posible hacerlo...

Para ver una versión Java Web Start, CLICK AQUI

package addfunctions;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Node;
import javafx.scene.input.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.util.Sequences;

var colors: Color[]=[Color.RED, Color.YELLOW,
Color.BLUE, Color.GREEN];

var mycircle = Circle {
centerX: 80, centerY: 80,
radius: 40
fill: Color.RED
onMousePressed: function(e) {
println("CLICK");
};
}

var mycircle2 = Circle {
centerX: 150, centerY: 150,
radius: 40
fill: Color.RED
onMousePressed: function(e) {
println("CLICK 2");
};
}

function addColorSwitch(node:Node) {
// obtiene la funcion original en el nodo
var origFunc: function(e:MouseEvent):Void=
node.onMousePressed;
// reemplaza evento en el nodo por nuevo evento
node.onMousePressed= function(e:MouseEvent) {
// incluye la funcion original del nodo
origFunc(e);
// agrega funcionalidad
var shape = (node as Circle);
// obtiene color actual en el circulo
var currentColor = shape.fill;
// busca la posicion del color en la secuencia
var pos = Sequences.indexOf(colors, currentColor);
// si es el ultimo colo de la secuencia, vuelve a cero
// si no, al siguiente elemento
if (pos == sizeof colors - 1) then
pos=0 else pos++;
// asigna nuevo color a circulo
shape.fill=colors[pos];
};
};

// agrega funcionalidad a
// onMousePressed en los circulos
addColorSwitch(mycircle);
addColorSwitch(mycircle2);

Stage {
width: 250, height: 250
scene: Scene {
content: [mycircle, mycircle2]
}
}

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