Curso de JavaFX

  • JavaFX es una librería open source nativa de Java.
  • Reemplaza a Swing en el desarrollo de interfaces visuales.
  • Aunque en su concepción estaba enfocado en la creación de interfaces para móviles, web y escritorio, actualmente se usa sólo en el escritorio.
  • Las aplicaciones creadas se pueden ejecutar en los escritorios Linux, Windows y Mac.

Añadir soporte de JavaFX a Eclipse

  1. Vamos a instalar un plugin en eclipse para tener este soporte: Menu help → Eclipse Marketplace → javafx → e(fx)clipse
  2. Project explorer → botón derecho del ratón → new → JavaFX Project

Crear una escena básica con JavaFX

public class MainEscenaBasica extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			//Especificamos el layout que definirá la distribución de los componentes en escena
			StackPane root = new StackPane();
			// Definimos la escena (la vista o ventana con la que el usuario va a interactuar)
			// Dicha escena recibe como parámetro la distrubución de sus componentes y sus medidas
			Scene scene = new Scene(root,400,400);
			// Para que una escena sea visible, debe ser añadida al escenario
			primaryStage.setScene(scene);
			// Hacemos visible el escenario
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

Detectar y procesar el click sobre un botón

Button btn = new Button("Púlsame");
btn.setOnAction(new EventHandler<ActionEvent>() {
	@Override
	public void handle(ActionEvent event) {
		System.out.println("hola");
	}			
});
root.getChildren().add(btn);

Usando lambdas (funciones anónimas):

En las lambdas no es necesario declarar el tipo de dato de los argumentos aunque sí que se puede hacer.

btn.setOnAction(event -> System.out.println("hola"));

Acceder al elemento con el que acabamos de interactuar

public static void btnPulsado(Event e) {
	Button b = (Button) e.getTarget();
	...
}

Layouts de JavaFX

StackPane

Superpone los objetos.

StackPane root = new StackPane();
Curso de JavaFX 1

GridPane

GridPane root = new GridPane();

// El primer parámetro es el objeto que estamos añadiendo a la regilla
// El segundo parámetro es la columna que ocupará dicho objeto
// El tercer parámetro es la fila que ocupará dicho objeto			
root.add(btn1, 1, 0);

Hacer que las celdas del gridpane ocupen el 100% del espacio disponible:

GridPane.setVgrow(btn2, Priority.ALWAYS);
GridPane.setHgrow(btn1, Priority.ALWAYS);
btn.setMaxWidth(Double.MAX_VALUE);			btn.setMaxHeight(Double.MAX_VALUE);

VBox

Coloca los elementos en vertical.

Curso de JavaFX 2

Para que el componente ocupe el 100% del layout que lo envuelve:

VBox.setVgrow(btn1, Priority.ALWAYS);

btn1.setMaxHeight(Double.MAX_VALUE);

HBox

Coloca los elementos en horizontal.

HBox root = new HBox();
Curso de JavaFX 3

Para que el componente ocupe el 100% del layout que lo envuelve:

HBox.setHgrow(btn1, Priority.ALWAYS);

btn1.setMaxWidth(Double.MAX_VALUE);

Priority.Always hace que el layout se extienda siempre que sea posible al máximo tamaño.

Añadir elementos a un layout

HBox root = new HBox(btn, btn2);
root.getChildren().add(btn);

Ejercicio layout

Hacer un layout con dos botones que ocupen el 100% del ancho.

Aplicar estilos en línea

root.setStyle("-fx-background-color:#333;");

Algunos componentes de JavaFX

Botón

Button btn = new Button("Calcular");

Cuadro de texto

TextField n2 = new TextField ();

ComboBox

ComboBox op = new ComboBox(options);

Para alimentar la ComboBox:

Con código Java:

ObservableList<String> options = FXCollections.observableArrayList("+","-","*");
final ComboBox op = new ComboBox(options);

Desde el fxml:

<?import javafx.collections.FXCollections ?>
<ComboBox fx:id="op" prefWidth="150.0">
	<items>
		<FXCollections fx:factory="observableArrayList">
			<String fx:value="+" />
			<String fx:value="-" />
			<String fx:value="*" />
			<String fx:value="/" />
		</FXCollections>
	</items>
	<value>
		<String fx:value="+" />
	</value>
</ComboBox>

Texto

Text txt = new Text("Ha ganado el jugador " + color);

Mensaje de alerta

Stage stage = (Stage)((Button)e.getSource()).getScene().getWindow();

final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(stage);
VBox dialogVbox = new VBox();
            
Text txt = new Text("Ha ganado el jugador " + color);
dialogVbox.setAlignment(Pos.CENTER);
VBox.setVgrow(txt, Priority.ALWAYS);
dialogVbox.getChildren().add(txt);
Scene dialogScene = new Scene(dialogVbox, 300, 200);
dialog.setScene(dialogScene);
dialog.show();  

Documentos FXML programando JavaFX

  • Es posible crear las interfaces visuales con código Java o con FXML (similar a HTML).
  • FXML soporta el estandar de CSS 2.1 y tiene algunas características de CSS3.
  • Los estilos que alteran el posicionamiento de las capas, como position, o display, no funcionan con JavaFX.
  • Cuenta con un Scene Builder para poder crear interfaces de manera más amigable.

Botón derecho sobre un paquete → new → New FXML Document

Configurar el Scene Builder en Eclipse

1. Para editar visualmente estos ficheros, podemos instalar el Scene Builder: https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html

2. Configurar el uso del Scene Builder en Eclipse: Window → Preferences → JavaFX → Scene Builder Executable → C:\Program Files (x86)\Oracle\JavaFX Scene Builder 2.0

3. Botón derecho sobre el fichero FXML que queremos editar → Open With Scene Builder

Cargar una escena definida con el scene Builder

Parent root = FXMLLoader.load(getClass().getResource("/view/tresenraya.fxml"));

Llamar a un método definido en nuestro .java desde nuestro fichero FXML

1. Tendremos que vincular nuestro fichero fxml a su correspondiente controlador:

Curso de JavaFX 5

2. Debemos vincular el nombre del método que queremos ejecutar a su correspondiente botón.

Curso de JavaFX 6

Y en el controlador, definir el método que será llamado con su correspondiente anotación.

@FXML
public void calcular() {
	System.out.println("Llega al método");
}

Acceder a un elemento de nuestro fichero .fxml

Hay varias formas, aunque la más sencilla, sería ponerle un identificador en el fxml:

Curso de JavaFX 7

Y luego hacer referencia a ese identificador desde el controlador:

@FXML
private TextField n1;

Hacer que un elemento ocupe el 100% de la capa que lo envuelve:

Con CSS:

.btn {
	-fx-max-width: Infinity;
	max-width: Infinity;
	-fx-max-height: Infinity;
	max-height: Infinity;
}

Con atributos:

<Node maxWidth="Infinity"/>

Con el Scene Builder:

  • Layout → maxWidth
  • Layout → VGrow, HGrou

Los códigos anteriores son equivalentes a este:

node.setMaxWidth(Double.MAX_VALUE);

Hacer una calculadora

Curso de JavaFX 8

Tres en raya – con FXML

  • Para detectar la pulsación de una casilla utilizaremos el evento onAction en lugar del evento onMouseClicked. De lo contrario si pulsasemos sobre el texto que hay en el botón, el target sería el label en lugar del propio botón.
  • Cada vez que pulsemos sobre una casilla, obtendremos la id de la casilla. Habremos asignado esa id a cada una de las casillas utilizando el Scene Editor. Utilizaremos esa id para ir rellenando con el color del jugador que ha pulsado sobre la casilla el array del tablero. Para recuperar la id de la casilla, utilizaremos el siguiente código:
@FXML
public void btnPulsado(Event e) {
	Button b = (Button) e.getTarget();
	int id = Integer.parseInt(b.getId());
	...
}
  • Después de cada tirada, se comprobará si alguien ha ganado llamando al método evaluateWin(String [] tablero);
  • El método evaluateWin(String [] tablero) mediante sucesivos if evaluará todas las posibilidades de que un jugador gane.

Tres en raya – sin FXML

Hacer el juego del tres en raya para dos jugadores.

  • Utilizando HBox y VBox, montaremos un tablero de 9 posiciones.
  • Iremos almacenando en un array de 9 posiciones las casillas a las que se vaya moviendo cada jugador.
  • Cada vez que un jugador pulse sobre una casilla, su color quedará modificado en función del jugador al que le tocaba mover.
  • Además, ada vez que un jugador pulse sobre una posición quedará modificado un array con el identificador del jugador almacenado en la posición correspondiente. Para ello, podemos vincular a cada botón un atributo que recuperaremos en el momento en que el botón sea pulsado:
// Para añadir un atributo al botón
btn.getProperties().put("index", i);

// Para recuperar un atributo del botón:
int id = (int)b.getProperties().get("index");
  • Después de cada tirada, se comprobará si alguien ha ganado, llamando al método evaluateWin(String [] tablero);
  • El método evaluateWin(String [] tablero) mediante sucesivos if todas las posibilidades de que un jugador gane.

Insertar imagen

Image img = new Image("/images/perro.jpg");
ImageView imgView = new ImageView(img);

Habremos creado la carpeta images dentro de la carpeta src de nuestro proyecto.

Insertar sonido

String musicFile = "sound/HakunaMatataItMeansNoWorries.mp3"; 
Media sound = new Media(new File(musicFile).toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(sound);
mediaPlayer.play();

sound será una carpeta creada en la raíz de nuestro proyecto.

Para cargar un sonido de internet, usaremos:

Media sound = new Media("https://pablomonteserin.com/res/html5/ex/HakunaMatataItMeansNoWorries.mp3");

Insertar formas

Curso de JavaFX 9

Círculo

Circle circle = new Circle(40); 
circle.setFill(Color.RED); // Color de relleno
circle.setStroke(Color.BLACK); // Color del borde
circle.setStrokeWidth(2.0); // Ancho del borde

Rectángulo

Rectangle rect = new Rectangle(0,0, 120, 75);
rect.setFill(Color.RED);

Parámetros:

  • x, y de la esquina superior izquierda del rectángulo (si es 0,0 se puede omitir).
  • ancho y alto del rectángulo

Línea

Line line = new Line(0, 0, 150, 50);

Parámetros:

  • x,y del punto de origin
  • x,y, del punto de destino

Arco

Arc arc = new Arc(0, 0, 50, 100, 0, 90);
arc.setType(ArcType.CHORD);

Parámetros:

  • centerX
  • centerY
  • radiusX → El ancho de la elipse de la que forma parte el arco.
  • radiusY → El alto de la elipse de la que forma parte el arco.
  • startAngle → El ángulo inicial del arco.
  • length → La extensión del arco en grados.

Polígono

Polygon poligono = new Polygon();
poligono.getPoints().addAll(30.0, 0.0,
	130.0, 0.0, 
	120.00, 50.0, 
	0.0, 50.0);
poligono.setStroke(Color.BLACK);

Parámetros:

  • Los pares de coordenadas x,y de cada uno de los puntos que componen el polígono.

Polilínea

Polyline polilinea = new Polyline(100.0, 0.0, 
	120.0, 20.0, 
	110.0, 140.0, 
	100.0, 60.0, 
	80.0, 40.0, 
	80.0, 120.0);

Parámetros:

  • Los pares de coordenadas x,y de cada uno de los puntos que componen el polígono.

Exportar proyecto

Exportar a un jar

Este fichero será ejecutable en linux, windows y mac siempre que el sitema operativo tenga instalada la máquina virtual de Java.

Botón derecho sobre el proyecto → Export … → Runnable JAR file

Exportar a un exe

1. Descargaremos la aplicación Launch4J.

2. En la aplicación debemos rellenar tres casillas:

  • Pestaña basic → Output file (debe terminar en .exe)
  • Pestaña basic → Jar (le pasamos la ubicación del jar que queremos convertir en ejecutable)
  • Pestaña JRE → Min JRE Versión → Yo puse la 1.5

Añadir soporte de JavaFX a Eclipse →

Aviso Legal | Política de privacidad