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

domingo, 22 de marzo de 2009

memeFX 0.2.2 : ImagesAccordion con ORIENTACION


Ahora se puede cambiar la orientación del componente de "acordeón", para que las imágenes se desplacen horizontal o verticalmente. Basta con incluir en la definición del componente, un:

orientation: ImagesAccordion.VERTICAL

para que las imágenes se muevan verticalmente.

viernes, 20 de marzo de 2009

memeFX v0.2


Ya está disponible la librería incluyendo una versión final de "acordeón de imágenes". La verdad que tiene muchas opciones para personalizar el componente. Además, permite enlazar algunas acciones del usuario con funciones.

Asi, por ejemplo, se podría hacer el que componente comience a tocar un MP3 distinto al pasar el mouse sobre los distintos elementos del "acordeón", y que muestre detalles sobre la música si se hace click sobre ese elemento. Pudiendo además dejar de tocar al abandonar el "acordeón" (al sacar el mouse de encima).

Proyecto memeFX y descarga código fuente, CLICK AQUI


Demo Java Web Start del ImageAccordion, CLICK AQUI

Esto me dio la idea de hacer una variación que permita crear un "acordeón de formulario", es decir, que haya varios formularios con campos, botones, etc. Y que uno pueda pasar de uno a otro igual que en el acordeón de imágenes. Voy a darle vueltas y veré que resulta.

miércoles, 18 de marzo de 2009

Un "acordeón" de imágenes


Este componente aun no está terminado, pero ya lo pueden probar usando el link de más abajo.

Lanzar demo Java Web Start, CLICK AQUI

Código fuente componente y demo, CLICK AQUI


El código para crear un "Acordeón de imágenes" es el siguiente:

var accordion = ImagesAccordion{
width: 650,
height: 350,
lineWidth: 1.0,
lineColor: Color.WHITE
images: [
ImageItem {
id: "moais",
caption: "Moais"
image: Image { url: "{__DIR__}moais.jpg"
}
message: "Easter Island (Rapa Nui) is a Polynesian island in the "
"southeastern Pacific Ocean, The island is a special "
"territory of Chile. Easter Island is famous for its "
"monumental statues, called moai."
messageArea: Rectangle2D {
minX: 30,
minY: 253,
width: 350,
height: 87
}
call: click
},
ImageItem {
id: "anakena",
caption: "Anakena"
image: Image { url: "{__DIR__}anakena.jpg"
}
message: "‘Anakena is a white coral sand beach in Rapa Nui..."
messageArea: Rectangle2D {
minX: 20,
minY: 233,
width: 360,
height: 107
}
messageFont: Font { size: 12
}
call: click
},
ImageItem {
id: "glacier",
caption: "Grey glacier"
image: Image { url: "{__DIR__}grey.jpg"
}
message: "The Glacier is in the south end..."
messageArea: Rectangle2D {
minX: 30,
minY: 270,
width: 320,
height: 70
}
call: click
},
ImageItem {
id: "torres",
caption: "Torres del Paine"
image: Image { url: "{__DIR__}paine.jpg"
}
message: "Spectacular mountain group in Torres del Paine..."
messageArea: Rectangle2D {
minX: 30,
minY: 270,
width: 320,
height: 70
}
call: click
},
ImageItem {
id: "salar",
caption: "Atacama desert"
image: Image { url: "{__DIR__}salar.jpg"
}
message: "The Atacama Desert is a virtually rainless plateau in Chile..."
messageArea: Rectangle2D {
minX: 20,
minY: 237,
width: 380,
height: 103
}
// messageFont: Font { size: 12 }
call: click
},
/* ImageItem {
id: "crayons",
caption: "Crayones"
message: "Recuerdos de la niñez"
image: Image { url: "{__DIR__}crayons.jpg"}
call: click
},*/
ImageItem {
id: "chaiten",
caption: "Chaiten"
image: Image { url: "{__DIR__}chaiten.jpg"
}
message: "Hell on Earth. Chaitén is a volcanic caldera..."
messageArea: Rectangle2D {
minX: 20,
minY: 270,
width: 420,
height: 70
}
call: click
}
]
effect: Reflection { fraction: 0.1,
}

};

function click(image:ImageItem) {
println(image.id);
}

sábado, 14 de marzo de 2009

MemeFX ... con Popup Menu (experimental)


Estuve haciendo algunos arreglos al experimento del menú flotante que desarrollé hace algún tiempo, y salvo algunos detalles, funciona sin problemas.

Acabo de subir el código de la biblioteca (memeFX), incluyendo este código y un demo, donde se aprecia como usar el menú flotante.

Para ver el demo (Java Web Start), haz CLICK AQUI

Para visitar el sitio web del proyecto, CLICK AQUI

Algo de código:

Primero, se crea un tipo de menú colgante... lo que puede incluir cambios a la apariencia del menú (colores, grosores, rotación, transparencia, esquinas redondeadas, etc.).


var popupCircle = PopupMenu{
corner: 20, padding: 8, borderWidth: 4,
opacity: 0.9, animate: true


content: [
MenuItem { text: "Animar circulo!",
callNode
: node },

MenuItem { text: "Mostrar nombre y posicion",
callPosId: positionId }

]
};

El tipo de función declarada para el Item (la función que ejecuta al ser seleccionado un item del menú), tiene que ver con los parámetros que retorna el menú al ser seleccionada la opción:

call = no retorna parametros, la función es declarada como:

function algo():Void { ... };

callId = retorna el ID del objeto sobre el que se utilizó el menú, la función es declarada como:

function algo(id:String):Void { ... };

callPos = retorna el MouseEvent que originó la aparición del menú. Permite, por ejemplo, obtener la posición del mouse al lanzar el menú (¿qué otros datos se pueden obtener de MouseEvent?). La función es declarada como:

function algo(e:MouseEvent):Void { ... };

callNode = retorna el Nodo sobre el que se utilizó el menú flotante. Permite manipular directamente el objeto (en este ejemplo, se anima el tamaño del círculo seleccionado). Si se quiere utilizar sobre un tipo particular de nodo, es necesario hacer un casting al tipo de objeto apropiado... ejemplo, si el tipo de objeto es un campo de texto: (node as SwingTextField).text="{node.id}" . La función es declarada como:

function algo(node:Node):Void { ... };

callPosId = retorna el MouseEvent que originó la aparición del menu y el ID del objeto sobre el que se utilizó (puede ser útil para saber en que parte del objeto se hizo click). La función es declarada como:

function algo(e:MouseEvent, id:String) { ... };

callPosNode = retorna el MouseEvent que originó la aparición del menu y el Nodo sobre el que se utilizó (puede ser útil para saber en que parte y sobre que objeto se hizo click). La función es declarada como:

function algo(e:MouseEvent, node:Node) { ... };

En este ejemplo agregaré dos círculos:

var circle1 = Circle {
id: "Cicle 1"
centerX: 100, centerY: 100
radius: 40, fill: Color.RED
};

var circle2 = Circle {
id: "Cicle 2"
centerX: 220, centerY: 300
radius: 80, fill: Color.YELLOW
};

Los ID son opcionales, pero pueden ser usados para reconocer sobre que objeto se lanzó el menú flotante (callId y callPosId).

A continuación, enlazo el menú con los círculos:

popupCircle.to(circle1);
popupCircle.to(circle2);

Se agregan las rutinas que serán ejecutadas por las opciones del menú (el código pudo ser incluido al definir el menú colgante).

function node(node:Node):Void {
Timeline {
repeatCount: 4
autoReverse: true
keyFrames: [
at (0s) {node.scaleX => 1.0;
node.scaleY => 1.0 }

at (0.2s) {node.scaleX => 1.4;
node.scaleY => 1.4}

]
}.play();
};

function positionId(e:MouseEvent, id:String):Void {
println("Mouse at {e.x},{e.y} over {id}");
}

Finalmente, se agregan los círculos y los menús al Stage:

Stage {
scene: Scene {
content: [
circle1,
circle2
PopupMenu.activateMenus()
]
}
}

viernes, 13 de marzo de 2009

MemeFX ... mi biblioteca para JavaFX


El nombre puede parecer "curioso", pero tiene una razón "intelectualoide" de ser...

Meme (se pronuncia MIM), responde a toda una teoría sobre la capacidad de las ideas para replicarse y evolucionar por si mismas, como seres vivos. La idea es que el diseño puede surgir del caos (suena a código abierto, ¿no?).

Se supone que a través de un proceso evolutivo y se selección natural, se consigue un resultado superior al original... ahora, como este proyecto es código abierto, y por lo mismo, fácilmente replicable y modificable (puede mutar y evolucionar libremente)... entonces, podría convertirse en un meme.

Veamos si el EFECTO MEME (MemeFX) ocurre con él... ;)

En este momento la biblioteca contiene sólo tres componentes, pero, no por eso no son útiles ;D ... la idea es que con el tiempo vaya creciendo. Tengo algunas ideas como incorporar controles para un menu flotante gráfico (si han mirado el blog, por ahí ya hice un intento), un componente de acordeón, componentes que permitan fácilmente asignar drag and drop a los elementos y definir areas para ser arrojados, un componente para simplificar que los applets sean arrastrables desde el navegador al escritorio (básicamente que genere el área de arrastre solo, porque de por sí es simple habilitar esa funcionalidad), etc. Las ideas son bienvenidas.

Por ahora, aquí está el código fuente de la biblioteca, demos Java Web Start con sus respectivos códigos fuentes y la documentación sobre como utilizarlos y personalizarlos.

Ojalá les sean de utilidad y puedan unirse al proyecto quienes se sientan motivados.

http://code.google.com/p/memefx/

Aquí hay más info sobre los Memes, si alguien tiene curiosidad.

lunes, 9 de marzo de 2009

Pronto liberaré este nuevo componente


No crean que abandoné mi pasión por el JavaFX ;D ... sólo he estado dedicado a desarrollar este componente que voy a liberar como código abierto.

JAVA WEB START DEMO

Sería genial si alguien con algo de tiempo me ayuda a integrar estos componentes (la perilla, el stagecontroller y este nuevo componente) en el proyecto JFXtras (CLICK). Mi problema es de falta de tiempo.

¿Algún voluntario?





package democombo;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import org.combofx.gauge.*;
import org.combofx.stage.*;
import org.combofx.knob.*;


/** Stage controller */
var cs = controlStage{
width: 1024, height: 600
initialPosition: controlStage.CENTER
checkMinHeight: true, minHeight: 600
checkMinWidth: true, minWidth: 1024
stickyBorders: true, limitBorders: true
};

// gauge component #1
var gauge1 = Gauge {
ui: BasicGauge{ }
primaryLabel: "Km/H"
secondaryLabel: "Speed"
secondaryLabelFont: Font { size: 15 };
min: 0.0, max: 100.0
scaleX: 0.72, scaleY: 0.72
translateX: -35, translateY: -42
speed: Gauge.SLOW
initialValue: 0
value: bind knob1.value
};

/** knob input #1 */
var knob1 = Knob {
ui: BasicKnob{ }
dialLinesNumber: 31
dialLinesLongEvery: 3
minAngle: 0, maxAngle: 720
translateX: 160, translateY: 160
min: 0, max: 100
scaleX: 0.5, scaleY: 0.5
value: 50
};


// gauge component #2
var control2 = CornerLLGauge{};
var gauge2 = Gauge {
ui: control2
primaryLabel: "Km/H"
secondaryLabel: "Current\nSpeed"
min: 0.0, max: 100.0
dialNumsVisibleEvery: 2
translateX: 300
speed: Gauge.SLOWEST
initialValue: 0
value: bind knob2.value
dialLongLinesColor: Color.YELLOW
// custom background color
background: control2.customBackground(Color.DARKBLUE)
};

/** knob input #2 */
var knob2 = Knob {
ui: BasicKnob{ }
dialLinesNumber: 31
minAngle: 0, maxAngle: 720
dialLinesLongEvery: 3
translateX: 470, translateY: 160
min: 0, max: 100
scaleX: 0.5, scaleY: 0.5
value: 50
};

// gauge component #3
var control3 = RectGauge{ };
var gauge3 = Gauge {
ui: control3
primaryLabel: "Km/H"
primaryLabelColor: Color.ORANGE
secondaryLabel: "Speed"
min: -100.0, max: 100.0
dialNumsLargeEvery: 2
largeNumberFont: Font { size: 16, oblique: true }
smallNumberFont: Font { size: 10, oblique: true }
translateX: 600, translateY: -7
scaleX: 0.94, scaleY: 0.94
speed: Gauge.INMEDIATE
initialValue: 0.1
value: bind knob3.value
dialLongLinesWidth: 4
internalLongRadDial: 118
dialShortLinesColor: Color.YELLOW
dialShortLinesWidth: 0.5
// custom background radial gradient
background: control3.customBackground(
RadialGradient {
centerX: 56, centerY: 56
focusX: 0.1, focusY: 0.1
radius: 103
proportional: false
stops: [
Stop {
color: Color.WHITE
offset: 0.0
},
Stop {
color: Color.DARKRED
offset: 1.0
}
]
})
};

/** knob input #3 */
var knob3 = Knob {
ui: BasicKnob{ }
dialLinesNumber: 31
minAngle: 0, maxAngle: 720
dialLinesLongEvery: 3
translateX: 830, translateY: 160
min: -100, max: 100
scaleX: 0.5, scaleY: 0.5
value: 0
};

// gauge component #4
var control4 = SquareGauge{};
var gauge4 = Gauge {
ui: control4
decorationVisible: false
primaryLabel: "Km/H"
secondaryLabel: "Speed"
secondaryLabelFont: Font { size: 15 }
valueColor: Color.CYAN
valueFont: Font {
size: 19,
oblique: true
name: "Verdana"
}
min: 0.0, max: 100.0
scaleX: 0.72, scaleY: 0.72
translateX: -35, translateY: 250
speed: Gauge.FAST
initialValue: 0
value: bind knob4.value
// custom gauge background color
background: control4.customBackground(Color.DARKGREEN)
// highlighted ranges
highlightRange: [
Gauge.range {
start: 0, end: 70
color: Color.GREEN
opacity: 0.8
},
Gauge.range {
start: 70, end: 90
color: Color.YELLOW
dialLongLinesColor: Color.YELLOW
dialShortLinesColor: Color.YELLOW
opacity: 0.5
}
Gauge.range {
start: 90, end: 100
color: Color.RED
dialLongLinesColor: Color.RED
dialShortLinesColor: Color.RED
opacity: 0.5
}
]
};

/** knob input #4 */
var knob4 = Knob {
ui: OrangeKnob{}
dialLinesNumber: 31
minAngle: 0, maxAngle: 720
dialLinesLongEvery: 3
translateX: 160, translateY: 450
min: 0, max: 100
scaleX: 0.5, scaleY: 0.5
value: 50
};

// gauge component #5
var control5 = SmallGauge{};
var gauge5 = Gauge {
ui: control5
primaryLabel: "Km/H"
secondaryLabel: "Speed"
min: 0.0, max: 100.0
dialNumsVisibleEvery: 2
translateX: 295, translateY: 290
speed: Gauge.FASTEST
initialValue: 0
value: bind knob5.value
valueColor: Color.RED
dialLongLinesColor: Color.RED
shadowColor: Color.RED
shadowX: 2, shadowY: 2
// custom background radial gradient
background: control5.customBackground(
RadialGradient {
centerX: 56, centerY: 56
focusX: 0.1, focusY: 0.1
radius: 103
proportional: false
stops: [
Stop {
color: Color.WHITE
offset: 0.0
},
Stop {
color: Color.BLACK
offset: 1.0
}
]
})
// highlighted gauge range
highlightRange: [
Gauge.range {
start: 80, end: 100,
color: Color.RED
dialLongLinesColor: Color.RED,
dialShortLinesColor: Color.RED
internalRad: 120, externalRad: 123
}
]
};

/** knob input #5 */
var knob5 = Knob {
ui: OrangeKnob{}
dialLinesNumber: 31
minAngle: 0, maxAngle: 720
dialLinesLongEvery: 3
translateX: 470, translateY: 450
min: 0, max: 100
scaleX: 0.5, scaleY: 0.5
value: 50
};

/** knob input noise #6 */
var knob6noise = Knob {
ui: OrangeKnob{ }
dialLinesNumber: 11
dialLinesLongEvery: 2
translateX: 730, translateY: 450
min: 0, max: 1
scaleX: 0.5, scaleY: 0.5
value: 0
};

// gauge component #6
var control6 = FlatRectInvGauge{};
var gauge6 = Gauge {
ui: control6
primaryLabel: ""
secondaryLabel: "Km/H"
secondaryLabelColor: Color.ORANGE
secondaryLabelFont: Font { size: 19 }
min: 0, max: 1
dialNumsVisibleEvery: 2
translateX: 600, translateY: 280
scaleX: 0.94, scaleY: 0.94
speed: Gauge.FAST
initialValue: 0.1
value: bind knob6.value
dialLongLinesWidth: 4
internalLongRadDial: 118
dialShortLinesColor: Color.ORANGE
dialShortLinesWidth: 0.5
noise: true, noiseLevel: bind knob6noise.value
reverseScale: true
dialNumsIntegerOnly: false
dialNumsDecimals: 1
useDots: true
displayVisible: false
decorationVisible: false
shadowX: 0, shadowY: 0
// highlighted gauge ranges
highlightRange: [
Gauge.range {
start: 0, end: 0.5
dialNumsColor: Color.ORANGE
},
Gauge.range {
start: 0.6, end: 0.8
color: Color.DARKRED
opacity: 0.3
internalRad: 0
},
Gauge.range {
start: 0.8, end: 1.0
color: Color.DARKRED
opacity: 0.6
internalRad: 0
}
]
// custom gauge background
background: Group { content: [
Rectangle {
x: 10, y: 10
arcHeight: 20, arcWidth: 20
width: 260, height: 180
fill: Color.RED
}
Circle {
centerX: 140, centerY: 52
radius: 125
fill: Color.DARKRED
opacity: 0.5
clip: Rectangle {
x: 15, y: 35,
width: 250, height: 180
arcHeight: 20, arcWidth: 20
}
}]
}
};

/** knob input #6 */
var knob6 = Knob {
ui: OrangeKnob { }
dialLinesNumber: 31
minAngle: 0, maxAngle: 720
dialLinesLongEvery: 3
translateX: 830, translateY: 450
min: 0, max: 1
scaleX: 0.5, scaleY: 0.5
value: 0.5
};


Stage {
// bind Stage (window) to the controller
width: bind cs.width with inverse
height: bind cs.height with inverse
x: bind cs.x with inverse
y: bind cs.y with inverse

scene: Scene {
content: [gauge1, knob1, gauge2, knob2, gauge3, knob3,
gauge4, knob4, gauge5, knob5, gauge6, knob6, knob6noise]
}
}


domingo, 15 de febrero de 2009

Stage Controller, almost 1000 downloads - Casi 1000 visitas para descargar el Stage Controller


Almost 1000 people visited the blog in a day to download the Stage Controller class. Thanks to all of you for your interest.

La verdad me sorprendió, pero casi 1000 personas visitaron el blog en un día para descargar el componente que controla los Stage... :D ... Visitas desde Nigeria, China, India, EEUU, Brazil, etc. Se ve que JavaFX está consiguiendo una comunidad global de desarrolladores, ¿no?


Gracias a todos por su interés.

sábado, 14 de febrero de 2009

My Google Code: Knob & Stage Controller / Perilla y controlador de Stage


Two of the components I developed are now hosted at Google Code. They include documentation about how to use them.

Dos de los componentes que desarrollé están ahora hospedados en Google Code. Ellos incluyen la documentación sobre como usarlos.

Knob control / Perilla
http://code.google.com/p/javafxknob/
Java Web Start demo

Stage Controller / Controlador de Stage
http://code.google.com/p/javafxstagecontroller/
Java Web Start demo

lunes, 2 de febrero de 2009

JavaFX: Menú flotante (popup menu)


Este código utiliza un menú flotante que implemente yo. Es un trabajo en progreso, así que tiene un par de detalles pendientes... pero, por ahora, quizás le puede servir a alguien para su aplicación o para aprender como funciona...



Como he dicho, estoy aprendiendo JavaFX script, así que es probable que haga cosas de maneras inapropiadas, no se crean que soy un experto! ;) ... aun... en todo caso, implementar el menú flotante me tomó sólo un par de horas desde que comencé (de cero), para que vean lo productivo que puede ser este lenguaje.

Por cierto, se pueden crear menús flotantes sin tanta configuración, sólo son necesarias las opciones (el texto de la opción [text:] y la función a las que están asociadas [call:]), las demás configuraciones son opcionales... y ojo, que hay bastantes opciones por probar y combinar.... por cierto, JavaFX script permite hacer combinaciones como el Timeline que agregué para que cambie el color del borde del menú flotante. Quizás puedes experimentar agregándole un Interpolador de resorte para que se vea más simpático al aparecer o elegir una opción, o que el menú aparezca rotando cuando es lanzado, etc.

Aquí está el proyecto Netbeans 6.5 completo (Download the complete Netbeans project here, alpha version).

package popupmenu;

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


var screenWidth=500.0;
var screenHeight=500.0;

// Primer menu flotante
var popupmenu=popupMenu{

corner:20
padding:8
borderWidth:4
borderColor:bind dynamicColor

// opciones del menu
content: [
menuItem { text:"Say Hello!", call: hello },
menuItem { text:"Again, say Hello!", call: again },

//menuSeparator { },
menuItem { text:"Say Bye!", call: bye }
]

};

// Timeline anima el borde del primer menu flotante
var dynamicColor:Color;
Timeline {
repeatCount:Timeline.INDEFINITE
autoReverse:true
keyFrames: [
at (0s) {dynamicColor => Color.YELLOW }
at (0.5s) {dynamicColor => Color.DARKBLUE}
at (1s) {dynamicColor => Color.LIGHTSALMON}
]
}.play();


// Segundo menu flotante
var popupCircle=popupMenu{

font: Font { size:20 };
gradient: LinearGradient { proportional: false
startX: 125.0, startY: 0.0, endX: 225.0, endY: 0.0
stops: [ Stop { offset: 0.0 color: Color.BLACK },
Stop { offset: 1.0 color: Color.RED } ] }
fill:Color.TRANSPARENT
stroke:Color.WHITE
highlight: Color.YELLOW
verticalSpacing:10

// opciones del menu
content: [
menuItem { text:"Multiline options\n"
"for your menu!", call: helloCircle },
menuItem { text:"This is a second\n"
"multiline option!", call: helloCircle },
]

};

// Tercer menu flotante
var popupmenu2=popupMenu{

font: Font { size: 18, name:"Verdana", embolden:true };
gradient: LinearGradient { proportional: true
stops: [ Stop { offset: 0.0 color: Color.GRAY },
Stop { offset: 1.0 color: Color.WHITE } ] }
fill:Color.TRANSPARENT
corner:20
padding:16
verticalSpacing:6
rotation:-25
highlight:Color.WHITE
highlightStroke:Color.RED

// opciones del menu
content: [
menuItem { text:"Say Hello!", call: hello },
menuItem { text:"Again, say Hello!", call: again },
menuItem { text:"Say Bye!", call: bye }
]

};


// funciones asignada a menus
function hello(e:MouseEvent):Void {
println("hello {e.x},{e.y}");
};

function helloCircle(e:MouseEvent):Void {
println("hello Circle {e.x},{e.y}");
};

function again(e:MouseEvent):Void {
println("hello, again {e.x},{e.y}");
};

function bye(e:MouseEvent):Void {
println("bye! {e.x},{e.y}");
};


Stage {
title: "Application title"
width: bind screenWidth with inverse
height: bind screenHeight with inverse
scene: Scene {
content: [
// agrega un fondo a la ventana
Rectangle {
fill: Color.BLUE
width: bind screenWidth
height: bind screenHeight
// le asigna un menu flotante
onMousePressed: function(e) {
popupmenu.event=e;
}
},
// crea un circulo
Circle {
// bloquea el click para que no dispare el menu flotante del fondo
blocksMouse:true
centerX: 100,
centerY: 100
radius: 40
fill: Color.RED
// le asigna un menu flotante
onMousePressed: function(e) {
popupCircle.event=e;
}
},
// crea un segundo circulo
Circle {
// bloquea el click para que no dispare el menu flotante del fondo
blocksMouse:true
centerX: 300,
centerY: 300
radius: 80
fill: Color.YELLOW
// le asigna un menu flotante
onMousePressed: function(e) {
popupmenu2.event=e;
}
},
// incluye los menus flotantes
popupmenu,
popupmenu2,
popupCircle
]
}
}

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]
}