Saltar la navegación

Paneles de diseño

En nuestra IU nosotros podríamos ir añadiendo controles colocándolos en una posición dada y dándoles un tamaño, pero esa no es la forma adecuada de hacerlo. La forma adecuada de posicionar los diferentes controles es utilizando paneles de diseño (Layout Pane).

Los paneles de diseño utilizan diferentes políticas para posicionar, dimensionar, espaciar, etc los controles que se añaden al mismo. Además a un panel de diseño no sólo podremos añadir controles si no que también podremos añadir otros paneles de diseño u otros elementos de JavaFX, por lo que a partir de ahora hablaremos de nodos.

Veamos los ejemplos más comunes de paneles de diseño:

Pane

Este panel nos ofrece total libertad para colocar los diferentes nodos. Los nodos se posicionan por las coordenadas en las que los añadimos. Este panel de diseño no se debe utilizar para realizar diseños robustos.

Este panel de diseño pertenece a la clase javafx.scene.layout.Pane.

Pane

El código utilizado para crear esta interfaz es el siguiente:

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Panel extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			Pane raiz = new Pane();
			Button bt1 = new Button("Botón 1");
			bt1.setLayoutX(10);
			bt1.setLayoutY(20);
			Button bt2 = new Button("Botón 2");
			bt2.setLayoutX(200);
			bt2.setLayoutY(100);
			Button bt3 = new Button("Botón 3");
			bt3.setLayoutX(50);
			bt3.setLayoutY(150);
			raiz.getChildren().addAll(bt1, bt2, bt3);
			
			Scene escena = new Scene(raiz, 300, 200);
			escenarioPrincipal.setTitle("Panel");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

HBox

Este panel posiciona los diferentes nodos que se le van añadiendo en una fila uno detrás de otro.

Este panel de diseño pertenece a la clase javafx.scene.layout.HBox.

HBox

Como puedes apreciar aparece un botón pegado al otro y pegados a los bordes. Este comportamiento lo podemos modificar cambiando las diferentes propiedades del mismo. Las más representativas son las siguientes propiedades:

  • padding: propiedad con la que podemos controlar la distancia entre los límites del panel y los bordes del panel.
  • spacing: propiedad que indica la separación entre los nodos.

En la siguiente imagen puedes observar la diferencia al modificar los valores de ambas propiedades.

HBox

También podemos cambiar la alineación de los nodos tal y como se muestra en la siguiente imagen, por medio de la propiedad alignment.

HBox

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class PanelHorizontal extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			HBox raiz = new HBox(10);
			raiz.setPadding(new Insets(10));
			raiz.setAlignment(Pos.CENTER_RIGHT);
			
			Button bt1 = new Button("Botón 1");
			Button bt2 = new Button("Botón 2");
			Button bt3 = new Button("Botón 3");
			
			raiz.getChildren().addAll(bt1, bt2, bt3);
			
			Scene escena = new Scene(raiz, 300, 50);
			escenarioPrincipal.setTitle("Panel horizontal");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

VBox

Este panel es similar al anterior con la salvedad que coloca los nodos en una columna uno debajo de otro. Al igual que con el anterior, podemos modificar las propiedades para cambiar su comportamiento.

Este panel de diseño pertenece a la clase javafx.scene.layout.VBox.

VBoxVBoxVBox
El código utilizado para crear la interfaz de la última imagen es el siguiente:
package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class PanelVertical extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			VBox raiz = new VBox(10);
			raiz.setPadding(new Insets(10));
			raiz.setAlignment(Pos.CENTER);
			
			Button bt1 = new Button("Botón 1");
			Button bt2 = new Button("Botón 2");
			Button bt3 = new Button("Botón 3");
			
			raiz.getChildren().addAll(bt1, bt2, bt3);
			
			Scene escena = new Scene(raiz, 250, 150);
			escenarioPrincipal.setTitle("Panel vertical");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

BorderPane

Este panel nos ofrece cinco regiones en las que añadir nodos: arriba, abajo, izquierda, derecha y centro. Este tipo de panel es muy utilizado para crear interfaces clásicas que arriba suelen tener una barra de menú, abajo una barra de estado, un panel de navegación a la izquierda, etc.

Este panel de diseño pertenece a la clase javafx.scene.layout.BorderPane.

BorderPane

El código utilizado para crear la interfaz de la imagen (aunque parezca algo enrevesado, lo he hecho para distinguir las diferentes zonas) es el siguiente:

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class PanelBorde extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			BorderPane raiz = new BorderPane();
			VBox vbIzquierda = new VBox();
			VBox vbDerecha = new VBox();
			HBox hbArriba = new HBox();
			HBox hbAbajo = new HBox();
			
			Button btIzquierda = new Button("Izquierda (LEFT)");
			Button btDerecha = new Button("Derecha (RIGHT)");
			Button btArriba = new Button("Arriba (TOP)");
			Button btAbajo = new Button("Abajo (BOTTOM)");
			Button btCentro = new Button("Centro (CENTER)");
			
			vbIzquierda.getChildren().add(btIzquierda);
			vbIzquierda.setAlignment(Pos.CENTER);
			vbIzquierda.setStyle("-fx-background-color: #dc143c");
			vbDerecha.getChildren().add(btDerecha);
			vbDerecha.setAlignment(Pos.CENTER);
			vbDerecha.setStyle("-fx-background-color: #dc143c");
			hbArriba.getChildren().add(btArriba);
			hbArriba.setAlignment(Pos.CENTER);
			hbArriba.setStyle("-fx-background-color: #b6e7c9");
			hbAbajo.getChildren().add(btAbajo);
			hbAbajo.setAlignment(Pos.CENTER);
			hbAbajo.setStyle("-fx-background-color: #b6e7c9");
			
			raiz.setLeft(vbIzquierda);
			raiz.setRight(vbDerecha);
			raiz.setTop(hbArriba);
			raiz.setBottom(hbAbajo);
			raiz.setCenter(btCentro);
			
			Scene escena = new Scene(raiz, 500, 300);
			escenarioPrincipal.setTitle("Panel de borde");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

StackPane

Este panel coloca los diferentes nodos uno encima del otro.

Este panel de diseño pertenece a la clase javafx.scene.layout.StackPane.

StackPane

El código utilizado para crear la interfaz de la imagen es el siguiente:

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.InnerShadow;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class PanelApilado extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			VBox raiz = new VBox();
			raiz.setAlignment(Pos.CENTER);
			
			StackPane spEmoji = new StackPane();
			Rectangle rectangulo = new Rectangle(100, 100);
			rectangulo.setFill(Color.web("#dc143c"));
			rectangulo.setStroke(Color.web("#b6e7c9"));
			rectangulo.setStrokeWidth(10);
			rectangulo.setArcHeight(40);
			rectangulo.setArcWidth(40);
			Label lbEmoji = new Label(";)");
			lbEmoji.setFont(new Font(60));
			spEmoji.getChildren().addAll(rectangulo, lbEmoji);
			InnerShadow is = new InnerShadow(10, Color.BLUE);
			DropShadow ds = new DropShadow(40, Color.DARKVIOLET);
			Light.Distant distancia = new Light.Distant();
			distancia.setColor(Color.LIGHTGRAY);
			distancia.setElevation(80);
			Lighting l = new Lighting(distancia);
			is.setInput(l);
			ds.setInput(is);
			spEmoji.setEffect(ds);
			
			raiz.getChildren().addAll(spEmoji);
			
			Scene escena = new Scene(raiz, 250, 250);
			escenarioPrincipal.setTitle("Panel apilado");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

GridPane

Este panel nos ofrece una cuadrícula de filas y columnas y en cada celda podemos colocar un nodo.

Este panel de diseño pertenece a la clase javafx.scene.layout.GridPane.

GridPane

Mediante las propiedades Hgap y Vgap podemos definir la distancia horizontal y/o vertical entre las celdas. También podemos modificar, entre otras, la propiedad padding.

GridPane

Este panel es muy utilizado para crear formularios con etiquetas y campos de texto alineados.

Formulario

El código utilizado para crear la interfaz anterior es el siguiente:

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class PanelCuadricula extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			GridPane raiz = new GridPane();
			raiz.setHgap(20);
			raiz.setVgap(20);
			raiz.setPadding(new Insets(20));
			
			Label lbNombre = new Label("Nombre:");
			Label lbApellidos = new Label("Apellidos:");
			Label lbDni = new Label("DNI:");
			TextField tfNombre = new TextField();
			TextField tfApellidos = new TextField();
			TextField tfDni = new TextField();
			
			raiz.add(lbNombre, 0, 0);
			GridPane.setHalignment(lbNombre, HPos.RIGHT);
			raiz.add(tfNombre, 1, 0);
			raiz.add(lbApellidos, 0, 1);
			GridPane.setHalignment(lbApellidos, HPos.RIGHT);
			raiz.add(tfApellidos, 1, 1);
			raiz.add(lbDni, 0, 2);
			GridPane.setHalignment(lbDni, HPos.RIGHT);
			raiz.add(tfDni, 1, 2);
			
			Scene escena = new Scene(raiz, 300, 160);
			escenarioPrincipal.setTitle("Panel en cuadrícula");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

FlowPane

Este panel dispone los nodos unos detrás de otros. Los nodos pueden flotar horizontalmente o verticalmente. Si la orientación es horizontal, colocará nodos uno detrás de otro y cuando llegue a la anchura del panel, seguirá colocando debajo de estos uno detrás de otro. Si es vertical los colocará uno debajo de otro y cuando llegue a la altura del panel los seguirá colocando a la derecha de los anteriores uno debajo de otro.

Este panel de diseño pertenece a la clase javafx.scene.layout.FlowPane.

FlowPaneFlowPane

El código utilizado para crear la primera interfaz es el que sigue. La segunda es una muestra de la misma interfaz redimensionada.

package javafx.panelesdiseno;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class PanelFlujo extends Application {

	@Override
	public void start(Stage escenarioPrincipal) {
		try {
			FlowPane raiz = new FlowPane();
			raiz.setPadding(new Insets(10));
			raiz.setAlignment(Pos.CENTER);
			
			Button bt1 = new Button("Botón 1");
			Button bt2 = new Button("Botón 2");
			Button bt3 = new Button("Botón 3");
			Button bt4 = new Button("Botón 4");
			Button bt5 = new Button("Botón 5");
			
			raiz.getChildren().addAll(bt1, bt2, bt3, bt4, bt5);
			
			Scene escena = new Scene(raiz, 400, 70);
			escenarioPrincipal.setTitle("Panel de flujo");
			escenarioPrincipal.setScene(escena);
			escenarioPrincipal.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

TilePane

Este panel es muy similar al anterior, aunque nos ofrece una cuadrícula de filas y columnas en las que irá colocando los nodos. Los nodos pueden colocarse horizontal o verticalmente y para colocar los nodos sigue la misma política que el panel anterior. Para definir la cuadrícula se utilizan las porpiedades prefColumns y prefRows. Aunque el número de filas y columnas puede variar dependiendo de la anchura y altura del panel.

Este panel de diseño pertenece a la clase javafx.scene.layout.TilePane.

AnchorPane

Este panel permite posicionar los nodos anclados a las caras del mismo por lo que nos ofrece total libertad para colocar los diferentes nodos. Al igual que Pane, no se debe utilizar para realizar diseños robustos.

Este panel de diseño pertenece a la clase javafx.scene.layout.AnchorPane.

AnchorPane

Para crear interfaces complejas lo más adecuado es combinar el uso de varios paneles de diseño para facilitarnos la tarea de diseño. Por ejemplo, para crear el formulario de la siguiente imagen he utilizado como panel principal un VBox. Dentro de éste he añadido:

  • Un GridPane de 3 filas y 2 columnas en el que he ido añadiendo las etiquetas y los campos de texto. 
  • Un HBox en el que he añadido los dos botones alineados a la derecha.

Formulario