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

lunes, 20 de agosto de 2012

Drag and Drop en JavaFX 2.0

Hola

Os pongo un enlace donde hay un ejemplo de como implementar el drag and drop.

http://blog.ngopal.com.np/2011/06/09/draggable-node-in-javafx-2-0/

Un saludo

lunes, 9 de abril de 2012

Editor grafico para JavaFX 2.0

Hola

Acabo de ver que Oracle a publicado un editor grafico para JavaFX.
Se puede descargar de aqui.

Cuando pueda le hecho un ojo y os cuento.

Un saludo

domingo, 25 de marzo de 2012

JavaFX 2.0. Vamos a crear una historia. Parte II

Ahora vamos con las implementaciones. Por ahora voy a incluir las implementaciones de actor y de la cabeza. No hay cuerpo pero ya se puede hablar y mover la cabeza.












- ActorImpl:


package es.historia.mueve.impl;

import es.historia.IActor;
import es.historia.ICabeza;
import es.historia.ICuerpo;
import javafx.scene.Group;

import javafx.scene.media.MediaPlayer;
import javafx.scene.media.Media;
import javafx.util.Duration;



/**
*
* @author Propietario
*/
public class ActorImpl implements IActor {
private ICabeza cabeza;
private ICuerpo cuerpo;
@Override
public Group dibujar() {
Group salida =new Group();
if (cabeza != null){
salida.getChildren().add(cabeza.dibujar());
cabeza.empezarMovimientoFijo();
}
if (cuerpo != null)
salida.getChildren().add(cuerpo.dibujar());
return salida;
}

@Override
public void mover() {
if (cabeza!= null)
cabeza.mover();
}

@Override
public void definir(ICabeza cabeza, ICuerpo cuerpo) {
this.cabeza = cabeza;
this.cuerpo= cuerpo;
}

@Override
public void hablar(String frase , final ICabeza cabeza) {
final MediaPlayer player = new MediaPlayer(new Media( frase));
player.play();
cabeza.empiezaHablar();
player.seek(Duration.ZERO);
player.setOnEndOfMedia(new Runnable() {

@Override
public void run() {
cabeza.terminaHablar();
}
});
}

@Override
public void establecerPosicion(int i, int i0) {
throw new UnsupportedOperationException("Not supported yet.");
}

Es esta clase podemos ver la funcionalidad de reproducir audio. Lo mas destacable del objeto MediaPlayer es que nos permite lanzar un hilo con una funcionalidad al "suceder" uno de los siguientes eventos:












- CabezaImpl:

package es.historia.parte.impl;

import es.historia.HistoriaExcepcion;
import es.historia.ICabeza;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.transform.Affine;
import javafx.util.Duration;

/**
*
* @author Propietario
*/
public class CabezaImpl implements ICabeza{
private Timeline timelineTodo;
private Timeline timelineBoca;
private ImageView visorParteSuperior;
private ImageView visorParteInferior;

@Override
public void establecerCara(String caraInferior, String caraSuperior) throws HistoriaExcepcion {
Image imagen1 = new Image(caraSuperior);
if (imagen1 == null || imagen1.isError())
throw new HistoriaExcepcion("La imagen " + caraSuperior + " no es accesible");
Image imagen2 = new Image(caraInferior);
if (imagen2 == null || imagen2.isError())
throw new HistoriaExcepcion("La imagen " + caraInferior + " no es accesible");
visorParteSuperior= new ImageView (imagen1);
visorParteInferior= new ImageView (imagen2);
}

@Override
public Group dibujar() {
Group salida =new Group();
salida.getChildren().add(visorParteSuperior);
salida.getChildren().add(visorParteInferior);
return salida;
}

@Override
public void mover() {
}

@Override
public void establecerPosicion(int x, int y) {
visorParteInferior.setLayoutX(x);
visorParteInferior.setLayoutY(y + visorParteSuperior.getImage().getHeight());
visorParteSuperior.setLayoutX(x);
visorParteSuperior.setLayoutY(y);
}

@Override
public void empezarMovimientoFijo() {
timelineTodo = new Timeline();
timelineTodo.setCycleCount(Timeline.INDEFINITE);
timelineTodo.setAutoReverse(true);
final Affine reflectTransform = new Affine();
//
visorParteSuperior.getTransforms().add(reflectTransform);
visorParteInferior.getTransforms().add(reflectTransform);
timelineTodo.getKeyFrames().addAll(new KeyFrame(Duration.ZERO,
new KeyValue(reflectTransform.mxxProperty(), -1, Interpolator.DISCRETE),
new KeyValue(reflectTransform.txProperty(), visorParteSuperior.getBoundsInLocal().getWidth(),
Interpolator.DISCRETE)
),
new KeyFrame(new Duration(2000L),
new KeyValue(reflectTransform.mxxProperty(), 1, Interpolator.DISCRETE),
new KeyValue(reflectTransform.txProperty(), 0, Interpolator.DISCRETE)),
new KeyFrame(new Duration(4000L),
new KeyValue(reflectTransform.mxxProperty(), -1, Interpolator.DISCRETE),
new KeyValue(reflectTransform.txProperty(), visorParteSuperior.getBoundsInLocal().getWidth(),
Interpolator.DISCRETE)
));
timelineTodo.play();
}

@Override
public void empiezaHablar() {
timelineBoca = new Timeline();
timelineBoca.setCycleCount(Timeline.INDEFINITE);
timelineBoca.setAutoReverse(true);
timelineBoca.getKeyFrames().addAll(new KeyFrame(Duration.ZERO,
new KeyValue(visorParteInferior.rotateProperty(), 40, Interpolator.DISCRETE),
new KeyValue(visorParteInferior.translateYProperty(), 30, Interpolator.DISCRETE)),
new KeyFrame(new Duration(100L),
new KeyValue(visorParteInferior.rotateProperty(), 0, Interpolator.DISCRETE),
new KeyValue(visorParteInferior.translateYProperty(), 0, Interpolator.DISCRETE)),
new KeyFrame(new Duration(200L),
new KeyValue(visorParteInferior.rotateProperty(), -40, Interpolator.DISCRETE),
new KeyValue(visorParteInferior.translateYProperty(), 30, Interpolator.DISCRETE)),
new KeyFrame(new Duration(300L),
new KeyValue(visorParteInferior.rotateProperty(), 0, Interpolator.DISCRETE),
new KeyValue(visorParteInferior.translateYProperty(), 0, Interpolator.DISCRETE)));

timelineBoca.play();
}

@Override
public void terminaHablar() {
timelineBoca.stop();
visorParteInferior.setRotate(0);
visorParteInferior.setTranslateY(0);
}

}

Lo mas destable es:

  • Se utilizan dos linas de tiempo. Una que no para nunca que cambia la orientacion de la cabeza y otra que solo funciona cuando se esta hablando y mueve la boca.
  • Las transformaciones. Siempre que se pueda se debe utilizar una propiedad (como setRotate) pero su la transformacion que se desea no se puede conseguir con una funcion que ofrece la clase entonces se puede usar transformaciones en forma de matriz(Affine).

viernes, 16 de marzo de 2012

JavaFX 2.0. Vamos a crear una historia. Parte I

Swing es una tecnología fácil y rápida para crear una interfaz grafica de una aplicación. En mi modesta opinión, JavaFX 2.0 ofrece la posibilidad de dar mas potencia a las interfaces graficas que puede ofrecer la tecnología Java. A JavaFX 2.0 lo único que le falta es tiempo de “incrustarse” en el uso cotidiano de los programadores.

Voy a explicar un framework muy sencillo para crear una historia con muñecos. Todo con JavaFX2.0. La idea es que busques una cara que quieres animar, como por ejemplo la de nuestro amigo George:















Recartar la cara con cualquier programa de edicion de imagenes, cortarla en dos partes (superior e inferior) y animarla poniendole voz:









En esta primera parte voy a centrarme en las interfaces; las implementaciones en el siguiente post.

El proyecto lo he creado con Netbeans 7.1. Se debe crear la siguiente estructura de clases:


















La idea es que en una clase donde se quiere crear una "historia" se debe crear actores que se componen de cuerpo y de cabeza.


- Main.java: Punto de entrada de la aplicación.

package es;

import es.historia.HistoriaExcepcion;
import es.historia.IActor;
import es.historia.ICabeza;
import es.historia.mueve.impl.ActorImpl;
import es.historia.parte.impl.CabezaImpl;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

/**
*
* @author Propietario
*/
public class Main extends Application {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws HistoriaExcepcion {
primaryStage.setTitle("Dibujo!");

// Se crea el actor
final IActor juguete = new ActorImpl();

// Se crea la cabeza
final ICabeza cabeza= new CabezaImpl();

// imagen que es la parte superior e inferior de la cabeza
cabeza.establecerCara("c:/caraInferior.JPG", "c:/caraSuperior.JPG");

// donde ponerlo dentro de la pantalla
cabeza.establecerPosicion(50,50);

// se define la cabeza del actor. El cuerpo para otro post.
juguete.definir(cabeza, null);

// Un boton para que hable
Button btn = new Button("Hablar");
btn.setOnAction(new EventHandler(){

public void handle(ActionEvent event) {

juguete.hablar("file:/uno_comoestas.wav", cabeza);
}

});


// un actor dibujado no es mas que un grupo de componentes JavaFx 2.0
Group group = juguete.dibujar();
group.getChildren().add(btn);

// apartir de aqui ya es como cualquier otra aplicacion JavaFx 2.0
Scene scene = new Scene(group, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
}

- HistoriaExcepcion: Excepcion para el uso dentro del framework

package es.historia;

/**
*
* @author Propietario
*/
public class HistoriaExcepcion extends Exception{

public HistoriaExcepcion(String string) {
super(string);
}
}

package es.historia;

- IActor: Requerimientos de una clase que sea una implementacion de un actor.

/**
*
* @author Propietario
*/
public interface IActor extends IMovimiento{
// Un actor es siempre una cabeza y un cuerpo
public void definir(ICabeza cabeza, ICuerpo cuerpo);
// accion de hablar
public void hablar(String frase,final ICabeza cabeza);
}

- ICabeza: Requerimientos de una clase que sea una implementacion de una cabeza.


package es.historia;

/**
*
* @author Propietario
*/
public interface ICabeza extends IMovimiento{
//una cara es una imagen superio y una cara inferior
public void establecerCara (String caraInferior, String caraSuperior) throws HistoriaExcepcion;

// definir posicion
public void establecerPosicion(int i, int i0);

// movimiento que se sucede siempre
public void empezarMovimientoFijo();

//movimiento cuando se habla
public void empiezaHablar();

// movimiento cuando se termina de hablar
public void terminaHablar();
}
- ICuerpo: Requerimientos de una clase que sea una implementacion de un cuerpo.

package es.historia;

/**
*
* @author Propietario
*/
public interface ICuerpo extends IMovimiento{
}

- IMarco: Requerimientos de una clase que sea una implementacion de un cuerpo.
package es.historia;

/**
*
* @author Propietario
*/
public interface IMarco {
}


- IMovimiento: Que funcionalidad debe de tener implementaciones que se puedan mover (cabeza, cuerpo, actor, etc..)
package es.historia;

import javafx.scene.Group;

/**
*
* @author Propietario
*/
public interface IMovimiento {
// dibujar la unidad (cuerpo, cabeza, etc..)
public Group dibujar ();
// mover la unidad
public void mover();
}

lunes, 23 de enero de 2012

El lenguaje XML de JavaFX 2.0 . FXML (I) - Paneles

Una escena de JavaFx 2.0 se puede componer como una pantalla de Swing y se puede evitar el uso de código “spaguetti” para ir definiendo los distintos componentes de los paneles que forman una pantalla gracias a FXML.

¿Cómo se usa un fichero FXML? La mejor forma de entender un fichero FXML es verlo como esa clase Java de código “spaguetti” puesta en notación XML. Tomemos como ejemplo la clase MiPantalla.java

public class MiPantalla extends JPanel{

public MiPantalla(){

inicializar();

}

private void inicializar(){

}

}

En una clase de código “spaguetti” MiPantalla si quieres definir un layout para un panel incluyes el import del tipo de layout y lo incluyes en una función

import java.awt.BorderLayout;

public class MiPantalla extends JPanel{

Public MiPantalla(){

inicializar();

}

Private void inicializar(){

setLayout(new BorderLayout());

}

}

Pues esto es prácticamente igual en un fichero FXML:


<?import javafx.scene.layout.AnchorPane?>

Ojo con este paso porque es la dinámica para usar FXML. Cuando se quiere usar una etiqueta nueva lo primero es incluir su “import” correspondiente en la parte superior del fichero XML. Una vez incluida se puede usar la etiqueta en el XML. Y esto es para todos los componentes igual.

Una vez que se incluye un componente en forma de etiqueta de XML también se puede acceder a todas sus propiedades de dicho componente en forma de atributo. Supone que tienes el siguiente código:

AnchorPane anchorPane = new AnchorPane();

anchorPane.setId("AnchorPaneId");

El equivalente en FXML seria:

<AnchorPane id="AnchorPaneId" prefHeight="500" prefWidth="800" xmlns:fx="http://javafx.com/fxml" fx:controller="es.ejemplo.Control">

</AnchorPane>

Es decir, el nombre del atributo es la función “setXXXX” quitándole el prefijo “set” y cambiando la primera letra a minúscula (ojo que Java es “Case sensitive”).

Respecto a los paneles que se pueden usar en JavaFx 2.0 son AnchorPane, BorderPane, FlowPane, GridPane, HBox, StackPane, TilePane y VBox.

Tambien cabe destacar el atributo fx:controller. Este atributo indica el nombre de la clase donde estarán “mapeados” todos los componentes y todas las acciones de esos componentes para que puedan interactuar con el resto de la aplicación. Esto se verá mejor en los siguientes post cuando se empiece con los componentes.