Mostrando entradas con la etiqueta funcion. Mostrar todas las entradas
Mostrando entradas con la etiqueta funcion. 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]
}
}

sábado, 17 de enero de 2009

JavaFX: Textos que giran y cambian de tamaño


Este ejercicio lo desarrollé para crear una clase que contiene sus propios timeline y que modifica el tamaño del font mientras gira el mensaje. Quizas lo más interesante de este ejercicio es la manera en que se modifica el tamaño del font desde el timeline. Otra cosa interesante es cómo el programa obtiene las dimensiones del texto para pintar el area que lo contiene (para ello es necesario que el texto sea definido en una variable y luego incluida en el contenido).




package experimenttext;

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


class myObject extends CustomNode {

// texto en el mensaje
public var message = "Nada aun";
// color del mensaje
public var color = Color.BLACK;
// color borde
public var stroke = Color.BLACK;
// color fondo
public var fill = Color.WHITE;
// tamaño maximo del font
public var max_size = 64.0;

// angulo de la rotacion
var angle: Number;
// tamaño del font
var size: Number;
// font del texto
var varfont = function(size:Number):Font {
Font{
name:"Verdana"
oblique:true;
size:size;
}
};


// mensaje desplegado
var geomText = Text {
content: bind message
font : bind varfont(size)
fill: bind color
textOrigin: TextOrigin.TOP
};

// rotacion del mensaje (un giro en 2 segundos)
var rotatetimeline = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
at(0s) { angle => 0 }
at(2s) { angle => 360 }
]
};

// variacion del tamaño del font (de 12 a MAX_SIZE en 1 segundos)
var fontsize = Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at(0s) { size => 12 }
at(0.3s) { size => max_size tween Interpolator.EASEBOTH}
]
};


// mensaje desplegado (compuesto por texto y rectangulo a su alrededor)
override protected function create():Node {

// inicia los timelines de la instancia
rotatetimeline.play();
fontsize.play();

Group {
content: [
// rectangulo
Rectangle {
width: bind geomText.boundsInLocal.width
height: bind geomText.boundsInLocal.height
stroke: bind stroke
fill: bind fill
},
// mensaje
geomText
]
// rotacion del conjunto (rect+mensaje)
rotate:bind angle
}
};

};

// primera instancia de mensaje
var msg=myObject{
translateX: 200
translateY: 150
message: "Primer mensaje"
};
// segunda instancia de mensaje
var msg2=myObject{
translateX: 300
translateY: 250
message: "Segundo mensaje"
color: Color.RED
stroke: Color.GREEN
fill: Color.YELLOW
max_size: 40.0
};
// tercera instancia de mensaje
var msg3=myObject{
translateX: 100
translateY: 350
message: "Tercer mensaje"
color: Color.WHITE
stroke: Color.BLUE
fill: Color.BLUE
max_size: 90.0
};

// aplicacion
Stage {
title: "Application title"
width: 800
height: 600
scene: Scene {
content: [
msg,
msg2,
msg3
]
}
}