Esta es una versión modificada del ejercicio anterior. Si se arrastra un objeto y este no cae dentro del destino, entonces rebota hacia el punto de origen.
Lo único que agregué fue que al crear el objeto guarda su posicion inicial en las variables original_x y original_y, y si detecta que no cae dentro del destino, ejecuta un Timeline que lo hace volver a su posición de origen.
Adicionalmente, hice algunos pequeños cambios para reemplazar el destino circular por un cuadrado de esquinas redondeadas.
Aquí hay una copia completa del proyecto Netbeans 6.5 (Download Complete Project)
Mostrando entradas con la etiqueta draggable. Mostrar todas las entradas
Mostrando entradas con la etiqueta draggable. Mostrar todas las entradas
lunes, 26 de enero de 2009
JavaFX: Objetos que son atraídos por su área de destino
Hola nuevamente, aquí va otro ejercicio entretenido e interesante. Probablemente se puede mejorar, pero por ahora, esta es la manera en que lo hice funcionar.
En parte, se basa en el código de ejemplos anteriores. Por ejemplo, el Interpolador de resorte es el mismo código que había usado antes. La clase DraggableObj es una versión modificada de un ejemplo anterior. Hay dos pequeñas clases que sólo describen un par de objetos simples y la clase principal que tiene un par de cosillas interesantes.
Por ejemplo, la clase principal tiene una lista de objetos para arrastrar, que sólo son "descritos" y que luego el programa transforma en los objetos gráficos definitivos, que el usuario manipula. También utiliza una función (toPaint) para consolidar todos los elementos gráficos que debe pintar y manipular.
Respecto a los ajustes que hace en DraggableObj al detectar que el objeto se acercó al area de destino: Lo que ocurre es que los círculos son posicionados por el centro, mientras los rectángulos/cuadrados son posicionados por la esquina superior izquierda (creo que hay una forma de mover ese punto, pero no lo he probado ni me consta que realmente exista... sólo tengo la impresión que leí algo como eso).
Aquí hay una copia del proyecto Netbeans 6.5 completo. (Download Complete Project)
Aquí va el código:
archivo Main.fx
archivo DraggableObj.fx
archivo MyObject.fx
archivo Area.fx
En parte, se basa en el código de ejemplos anteriores. Por ejemplo, el Interpolador de resorte es el mismo código que había usado antes. La clase DraggableObj es una versión modificada de un ejemplo anterior. Hay dos pequeñas clases que sólo describen un par de objetos simples y la clase principal que tiene un par de cosillas interesantes.
Por ejemplo, la clase principal tiene una lista de objetos para arrastrar, que sólo son "descritos" y que luego el programa transforma en los objetos gráficos definitivos, que el usuario manipula. También utiliza una función (toPaint) para consolidar todos los elementos gráficos que debe pintar y manipular.
Respecto a los ajustes que hace en DraggableObj al detectar que el objeto se acercó al area de destino: Lo que ocurre es que los círculos son posicionados por el centro, mientras los rectángulos/cuadrados son posicionados por la esquina superior izquierda (creo que hay una forma de mover ese punto, pero no lo he probado ni me consta que realmente exista... sólo tengo la impresión que leí algo como eso).
Aquí hay una copia del proyecto Netbeans 6.5 completo. (Download Complete Project)
Aquí va el código:
archivo Main.fx
package placeobject;
import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.Node;
var destinationMessage:Text;
// area de destino
var destinationArea=Circle{
opacity: 0.5
centerX: Area.destination.x
centerY: Area.destination.y
radius: Area.destination.radius
fill: Area.destination.color
};
// mensaje para destino
destinationMessage=Text {
font: Font { size: 24 }
x: bind messagePosX, y: bind messagePosY
content: "Destino"
textOrigin:TextOrigin.TOP
}
// calcula posicion para mensaje
var messagePosX = Area.destination.x - destinationMessage.boundsInLocal.width/2;
var messagePosY = Area.destination.y - destinationMessage.boundsInLocal.height/2;
// lista de objetos por arrastrar
var objects= [
MyObject {type:"square", size:100, x:50, y:50, color:Color.BLUE},
MyObject {type:"circle", size:100, x:250, y:50, color:Color.RED},
MyObject {type:"square", size:80, x:50, y:250, color:Color.PURPLE},
MyObject {type:"circle", size:120, x:200, y:200, color:Color.YELLOW}
];
// carga objetos en una secuencia (array)
var list:Node[];
for (obj in objects) {
// si es un cuadrado
if (obj.type=="square") then {
var rect=DraggableObj{
translateX:obj.x
translateY:obj.y
content: Rectangle{
width:obj.size
height:obj.size
fill:obj.color
}
};
insert rect as Node into list;
}
// si es un circulo
if (obj.type=="circle") then {
var circ=DraggableObj{
translateX: obj.x + obj.size/2
translateY: obj.y + obj.size/2
isCircle: true
content: Circle{
radius: obj.size/2
fill:obj.color
}
}
insert circ as Node into list;
}
};
// obtiene los objetos a pintar
function toPaint():Node[] {
// array para objetos
var objs:Node[];
// crea area de destino
var dest=Group {
content: [
destinationArea,
destinationMessage
]
};
// agrega destino a la lista
insert dest into objs;
// agrega los objetos a la lista
insert list into objs;
// retorna un array de objetos por pintar
return objs;
};
var stage=Stage {
title: "Application title"
width: 600
height: 600
scene: Scene {
content:
bind toPaint()
}
};
archivo DraggableObj.fx
package placeobject;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.animation.Timeline;
import javafx.animation.Timeline.*;
import javafx.animation.Interpolator;
import javafx.animation.Interpolator.*;
import javafx.geometry.*;
def spring = SpringInterpolator { bounce: true};
public class DraggableObj extends CustomNode {
public var content: Node[];
public var isCircle = false;
var endX = 0.0;
var endY = 0.0;
var startX = 0.0;
var startY = 0.0;
var op:Number=100;
var scale:Number=100;
var final:Point2D;
var origin:Point2D;
var original_width=0.0;
var original_height=0.0;
// vuelve escala a 100%
var s=Timeline {
keyFrames: [
at (1.5s) { scale => 100.0 tween spring},
]
};
// aumenta escala de 100% a 150%
var i=Timeline {
keyFrames: [
at (0s) { scale => 100.0 },
at (0.3s) { scale => 150.0},
]
};
// desplazamiento hacia el centro de destino
var dxy=Timeline {
keyFrames: [
at (0s) { endX => origin.x; endY => origin.y },
at (1s) { endX => final.x tween spring; endY => final.y tween spring},
]
};
override function create() : Node {
// crea objeto
var newNode = Group {
translateX: bind endX
translateY: bind endY
content: bind content
opacity: bind op/100.0
scaleX: bind scale/100.0
scaleY: bind scale/100.0
onMousePressed: function(e) {
startX = e.dragX-endX;
startY = e.dragY-endY;
dxy.stop();
s.stop();
i.playFromStart();
}
onMouseDragged: function(e) {
endX = e.dragX-startX;
endY = e.dragY-startY;
}
onMouseReleased: function(e) {
s.time=0s;
s.play();
checkDestination();
}
};
// obtiene tamaño del objeto
original_width=newNode.boundsInLocal.width;
original_height=newNode.boundsInLocal.height;
// retorna el objeto creado (la instruccion return es opcional)
return newNode;
}
// chequea si esta proximo al destino
function checkDestination() {
// obtiene coordenadas y tamaño del destino
var dest=Rectangle2D {
minX:Area.destination.x - Area.destination.radius
minY:Area.destination.y - Area.destination.radius
width:Area.destination.radius*2
height:Area.destination.radius*2
};
// verifica si el area del objeto arrastrado y el destino coinciden
if (dest.intersects(this.boundsInScene)) then {
// punto de origen para la animacion (posicion actual del objeto)
origin=Point2D{x:endX, y:endY};
// cuanto debe moverse el objeto para alcanzar el destino
final=this.sceneToLocal(Area.destination.x, Area.destination.y);
// si no es un circulo (y el centro esta desplazado a la esquina
// superior izquierda del rectangulo/cuadrado)
if (not isCircle) {
// ajusta cuanto debe moverse
final=Point2D {
// menos la mitad del ancho y alto
x: final.x - original_width / 2;
y: final.y - original_height / 2;
};
};
// inicia animacion para alcanzar el centro del destino
dxy.playFromStart();
};
}
}
archivo MyObject.fx
package placeobject;
import javafx.scene.paint.Color;
public class MyObject {
public var type:String;
public var size:Number;
public var x:Number;
public var y:Number;
public var color:Color;
}
archivo Area.fx
package placeobject;
import javafx.scene.paint.Color;
public class Area {
public var x:Number;
public var y:Number;
public var radius:Number;
public var color:Color;
}
public var destination=Area {
x:400
y:400
radius:100
color:Color.RED
};
sábado, 24 de enero de 2009
JavaFX: Applet con area para arrastrarlo
Esta versión posee un area delimitada que permite arrastrar el applet fuera del navegador. La versión anterior permitía arrastrar el applet desde cualquier area del applet. El inconveniente de la versión anterior, es que no permite utilizar drag and drop (arrastrar elementos) dentro del applet, porque arrastraba el applet completo fuera del navegador.
package advdragapplet;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.text.TextOrigin;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.input.MouseEvent;
import javafx.animation.Timeline;
import javafx.stage.AppletStageExtension;
// area para arrastrar el applet
var dragArea:Group;
dragArea = Group {
opacity: 0.5
// la barra solo aparece si es un applet y puede ser arrastrado
visible: bind AppletStageExtension.appletDragSupported
onMouseDragged:function(e:MouseEvent):Void {
stage.x += e.dragX;
stage.y += e.dragY;
}
content: [
Rectangle {
x: 0
y: 0
width: 140
height: 20
fill: Color.YELLOW
},
Text {
font: Font {
size: 12
}
x: 10,
y: 5
textOrigin:TextOrigin.TOP
content: "Arrastrame / Drag me"
}
]
};
var x:Number;
Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at(0.0s) { x => 40}
at(0.5s) { x => 224}
]
}.play();
var stage=Stage {
title: "Draggable Applet"
width: 280
height: 116
scene: Scene {
fill:Color.PURPLE
content: [
Circle {
centerX: bind x,
centerY: 40
radius: 40
fill: Color.CYAN
},
dragArea,
]
}
extensions: [
AppletStageExtension {
shouldDragStart: function(e): Boolean {
e.primaryButtonDown and dragArea.hover;
}
}
]
}
Etiquetas:
area,
arrastrable,
arrastrar,
bar,
barra,
browser,
desktop,
drag and drop,
draggable,
encabezado,
escritorio,
header,
java,
javafx 1.0,
lesson,
navegador,
source code,
zone
JavaFX: Applet Arrastrable
Una de las nuevas funcionalidades de Java 6 update 10 es la posibilidad de crear applets "arrastrables" (que el usuario puede "arrastrar" fuera de la página de su navegador, y convertir en una aplicación de escritorio). Esta funcionalidad también está disponible -con un mínimo de trabajo- para los applets JavaFX.
Lo único que tienes que tienes que agregar a tu código es:
Y posteriormente, incluir este trozo como atributo del Stage:
Listo, los usuarios de tu applet ya pueden arrastrarlo al escritorio y crear un short-cut (automáticamente) para re-lanzar el applet, sin siquiera tener que abrir su navegador.
Nota: Para desinstalar desde Windows un applet convertido en aplicación de escritorio, tienes que ir al Panel de Control y desinstalarlo como cualquier otro programa.
Aquí está el código del ejemplo en video:
Lo único que tienes que tienes que agregar a tu código es:
import javafx.stage.AppletStageExtension;
Y posteriormente, incluir este trozo como atributo del Stage:
extensions: AppletStageExtension {
shouldDragStart: function(e: MouseEvent): Boolean {
e.primaryButtonDown;
}
}
Listo, los usuarios de tu applet ya pueden arrastrarlo al escritorio y crear un short-cut (automáticamente) para re-lanzar el applet, sin siquiera tener que abrir su navegador.
Nota: Para desinstalar desde Windows un applet convertido en aplicación de escritorio, tienes que ir al Panel de Control y desinstalarlo como cualquier otro programa.
Aquí está el código del ejemplo en video:
package draggableapplet;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.text.Font;
import javafx.scene.input.MouseEvent;
import javafx.animation.Timeline;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.stage.AppletStageExtension;
var x:Number;
Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at(0.0s) { x => 40}
at(1.0s) { x => 224}
]
}.play();
Stage {
title: "Application title"
width: 270
height: 116
extensions: AppletStageExtension {
shouldDragStart: function(e: MouseEvent): Boolean {
e.primaryButtonDown;
}
}
scene: Scene {
fill:Color.YELLOW
content: [
Circle {
centerX: bind x,
centerY: 40
radius: 40
fill: Color.RED
},
Text {
font: Font {
size: 24
}
x: 10,
y: 28
textOrigin:TextOrigin.TOP
content: "Arrastrame / Drag me"
}
]
}
}
Etiquetas:
aplicacion,
applet,
application,
arrastrable,
arrastrar,
browser,
desktop,
distribucion,
distribuir,
distribution,
drag and drop,
draggable,
escritorio,
instalar,
java,
javafx,
navegador
domingo, 18 de enero de 2009
JavaFX: Objetos arrastrables con "efectos"
Este ejemplo incluye 3 clases:
1) Una clase (SpringInterpolator) que define un nuevo tipo de "interpolador" que genera un movimiento "elástico" (de resorte)
2) Una clase (DraggableObj) que permite que los elementos asignados sean "arrastrables" (drag and drop).
3) La clase principal (Main) que implementa la aplicación y que agrega 4 elementos para arrastrar por la ventana.
archivo SpringInterpolator.fx
archivo DraggableObj.fx
archivo Main.fx
1) Una clase (SpringInterpolator) que define un nuevo tipo de "interpolador" que genera un movimiento "elástico" (de resorte)
2) Una clase (DraggableObj) que permite que los elementos asignados sean "arrastrables" (drag and drop).
3) La clase principal (Main) que implementa la aplicación y que agrega 4 elementos para arrastrar por la ventana.
archivo SpringInterpolator.fx
package DraggableClass;
import javafx.animation.SimpleInterpolator;
import java.lang.Math;
public class SpringInterpolator extends SimpleInterpolator {
// amplitud de la onda
// controla que tan lejos puede llegar el objeto desde su punto final
public-init var amplitude:Number = 1.0;
// determina el peso del objeto
// hace el movimiento de la onda mas grande y llega mas lejos
public-init var mass:Number = 0.058;
// rigidez del movimiento de la onda o resolte
// hace la onda mas corta o ceñida
public-init var stiffness:Number = 12.0;
// hace la onda de fase, de modo que el objeto
// no acabe en el lugar de descanso.
// esta variable generalmente no cambia
public-init var phase:Number = 0.0;
// si actua como un resorte normal o rebota
public-init var bounce:Boolean = false;
// usado para calculos internos
var pulsation:Number;
init {
this.pulsation = Math.sqrt(stiffness / mass);
}
// ecuacion del resorte
override public function curve(t: Number) : Number {
var t2 = -Math .cos(pulsation * t + phase + Math.PI) * (1 - t) * amplitude ;
// usa el valor absoluto de la distancia si rebota
if(bounce) {
return 1 - Math.abs(t2);
} else {
return 1 - t2;
}
}
}
archivo DraggableObj.fx
package DraggableClass;
import javafx.scene.Group;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.animation.Timeline;
import javafx.animation.Timeline.*;
import javafx.animation.Interpolator;
import javafx.animation.Interpolator.*;
public class DraggableObj extends CustomNode {
public var content: Node[];
var endX = 0.0;
var endY = 0.0;
var startX = 0.0;
var startY = 0.0;
var op:Number=100;
var scale:Number=100;
// produce un parpadeo rapido al
// al soltar los objetos arrastrados
var t = Timeline {
repeatCount: 3
keyFrames: [
at (0s) { op => 100.0 },
at (0.05s) { op => 0.0 }
]
}
// instancia el interpolador de resorte
def spring = SpringInterpolator { bounce: true};
// escala objetos con efecto de resorte
var s = Timeline {
keyFrames: [
at (1.5s) { scale => 100.0 tween spring},
]
};
// escala objectos de tamano original
// a tamano 50% mas grande al hacer
// click sobre ellos
var i = Timeline {
keyFrames: [
at (0s) { scale => 100.0 },
at (0.3s) { scale => 150.0},
]
};
override function create() : Node {
// produce una variacion constante en la
// opacidad de los elementos arrastrables
Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at (0s) { op => 70.0 },
at (0.3s) { op => 100.0 tween Interpolator.EASEBOTH}
]
}.play();
Group {
translateX: bind endX
translateY: bind endY
content: bind content
opacity: bind op/100.0
scaleX: bind scale/100.0
scaleY: bind scale/100.0
onMouseDragged: function(e) {
endX = e.dragX-startX;
endY = e.dragY-startY;
}
onMousePressed: function(e) {
startX = e.dragX-endX;
startY = e.dragY-endY;
s.stop();
i.playFromStart();
}
onMouseReleased: function(e) {
t.playFromStart();
s.time=0s;
s.play();
}
};
}
}
archivo Main.fx
package DraggableClass;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.input.MouseEvent;
var newCircle=DraggableObj{
translateX:700
translateY:200
content: Circle {
radius: 100
fill: Color.RED
opacity:0.75
}
};
// este objeto incluye un ARRAY (arreglo) de figuras
var newCircle2=DraggableObj{
translateX:200
translateY:200
content: [
Circle {
opacity:0.5
fill:Color.BLUE
radius:70
},
Rectangle {
translateX:-50
translateY:-50
width:100
height:100
rotate:45
fill:Color.GREEN
opacity:0.5
}
]
};
var newImage=DraggableObj{
translateX:200
translateY:500
content: ImageView {
opacity:0.8
preserveRatio:true
fitWidth:200
image: Image {
// url: "file:/C:/Users/myuser/Pictures/2008a.png"
url: "http://www.google.com/intl/en_ALL/images/logo.gif"
}
}
}
var newRect=DraggableObj{
translateX:700
translateY:500
content: Rectangle {
width:100
height:100
rotate:45
fill:Color.PURPLE
opacity:0.5
}
};
Stage {
title: "Application title"
width: 1200
height: 750
scene: Scene {
// Incluye un ARRAY de objetos
content: [
newCircle,
newCircle2,
newImage,
newRect
]
}
}
Etiquetas:
arrastrable,
arrastrar,
boucing,
bounce,
codigo fuente,
como,
contenedor,
drag and drop,
draggable,
efecto,
efectos,
ejemplo,
elastico,
example,
how to,
javafx,
objeto,
resorte,
source code,
spring
lunes, 8 de diciembre de 2008
JavaFX: Circulo arrastrable que cambia de color
Este ejemplo dibuja un circulo de radio "rad=60", que cambia de color y que puede ser arrastrado con el mouse. Además, incluye una función que se "dispara" al cambiar el color del círculo (color=0 on replace oldColor {})
package javafxclasses;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.scene.input.*;
import javafx.scene.shape.Circle;
import javafx.scene.transform.Transform;
def rad=60.0;
var x1=rad;
var y1=rad;
var dx:Number;
var dy:Number;
var colors = [Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW];
var color=0 on replace oldColor {
println("\nALERT! El color cambio!");
println("Antiguo color: {oldColor}");
println("Nuevo color: {color}");
}
Stage {
title: "Application title"
width: 400
height: 400
scene: Scene {
content: [
Circle {
centerX: bind x1;
centerY: bind y1;
radius: rad
fill: bind colors[color]
onMousePressed: function(e) {
// obtiene distancia entre el centro del círculo
// arrastrado y la posición del mouse al hacer click
dx = x1 - e.x;
dy = y1 - e.y;
if (++color==sizeof colors)
color=0;
}
onMouseDragged : function(e) {
// calcula el centro del círculo aplicando la
// diferencia respecto al centro del círculo al
// comenzar a arrastrarlo
x1 = e.x + dx;
y1 = e.y + dy;
}
}
]
}
}
Etiquetas:
arrastrable,
arrastrar,
drag and drop,
draggable,
javafx,
objeto,
on replace
Suscribirse a:
Entradas (Atom)