style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Iniciando con JavaFX: Layouts - Ejemplos de uso.

Exordio

Mas allá de querer impresionar al lector con palabras rebuscadas lo que pretendo es advertirle de lo que esta por ver. Contenido sobre los layouts y su uso básico en JavaFX. Esto no es un discurso, ni una novela pero debo advertir que por cuestiones de preferencias personales he decidido crear una publicación lo suficientemente grande como para resultar incomoda de leer. Sin mas que agregar ¡Que comience el codeo!

Layout VBox

Como habíamos mencionado este layout nos permite colocar nodos hijos en una columna , lista vertical o caja vertical, escojan la definición que prefieran.
Aclaración: usare un nodo de tipo Button para ejemplificar el uso de los diferentes layouts, ya que al tener un tamaño definido sera mas fácil de apreciar las características del layout.
Iniciemos con el primer ejemplo:

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

/**
 *
 * @author kalt
 */

public class VBoxTest extends Application {

    private VBox cajaVertical;//Declaramos un objeto de tipo VBox

    @Override
    public void start(Stage stage) {
        cajaVertical = new VBox();//Inicializamos el objeto
       
        cajaVertical.getChildren().add(new Button("Boton 1"));//agregamos un nodo hijo de tipo Button
        cajaVertical.getChildren().add(new Button("Boton 2"));//agregamos un nodo hijo de tipo Button
        cajaVertical.getChildren().add(new Button("Boton 3"));//agregamos un nodo hijo de tipo Button
       
        Scene s = new Scene(cajaVertical);//Creamos la escena y le pasamos como parámetro nuestro layout
        stage.setScene(s);//Seteamos en la ventana el layout
        stage.show();//y mostramos la ventana
    }
}

El resultado es el siguiente:

Se nota en la imagen que los botones están pegados uno después del otro y que están al ras de la ventana, y ademas agregamos los nodos hijos en tres lineas, escribiendo código innecesario, para modificar eso haremos lo siguiente.

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

/**
 *
 * @author kalt
 */

public class VBoxTest extends Application {

    private VBox cajaVertical;

    @Override
    public void start(Stage stage) {
        cajaVertical = new VBox(10);//Asignamos 10 pixeles de separacion entre los nodos
        cajaVertical.setPadding(new Insets(15)); //Agregamos un relleno de 15 pixeles para separarlo del borde de la ventana
        cajaVertical.getChildren().addAll(new Button("Boton 1"), new Button("Boton 2"), new Button("Boton 3"));//llamando al metodo addAll podemos agregar nodos en una sola linea
       
        Scene s = new Scene(cajaVertical);
        stage.setScene(s);
        stage.show();
    }
}

El resultado:

Para la manipulación básica de este layout esto basta.

Layout HBox

Este layout es exactamente igual que el anterior a excepción de que en lugar de ser una fila vertical, esta es horizontal. El constructor y el método setPadding están disponibles, ademas de que los nodos hijos se agregan de la misma forma. Por esta razón no haremos código de este layout.

Layout BorderPane

Este layout permite agregar 5 nodos hijos en distintas posiciones, top, left, right, bottom y center. Veamos un ejemplo

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

/**
 *
 * @author kalt
 */

public class BorderPaneTest extends Application {

    private BorderPane raiz;
   
    @Override
    public void start(Stage stage)  {
        raiz = new BorderPane();
       
        raiz.setTop(new Button("TOP"));
        raiz.setBottom(new Button("BOTTOM"));
        raiz.setLeft(new Button("LEFT"));
        raiz.setRight(new Button("RIGHT"));
        raiz.setCenter(new Button("CENTER"));
       
        Scene scene = new Scene(raiz);
       
        stage.setScene(scene);
        stage.show();
    }    
}

Resultado:

Como podemos observar top, left y bottom aparecen están alineados de manera vertical, incluso si agrandamos la ventana veremos como left esta pegado a top.

A continuación podemos observar en una imagen bastante cutre y simple como se comporta el BorderPane

Las flechas significan que puede agrandarse o encogerse, según la posición de la flecha. Las lineas significan que ese tamaño permanece, osea, no se modifica. Ya sea alto o ancho.

Layout FlowPane

Este tipo de layout es parecido al HBox y al VBox. Puede ser como cualquiera de los dos, todo depende del constructor, veamos un ejemplo:

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

/**
 *
 * @author kalt
 */

public class FlowPaneTest extends Application {
    private FlowPane flow;
    @Override
    public void start(Stage stage) throws Exception {
        flow = new FlowPane();
        flow.getChildren().addAll(new Button("Boton 1"), new Button("Boton 2"), new Button("Boton 3"));
       
        Scene s = new Scene(flow);
        stage.setScene(s);
        stage.show();
    }
   
}

El resultado es:

Como podemos observar, por defecto el constructor vació del flowpane lo crea como horizontal. Al constructor no le podemos pasar simplemente el espacio entre los nodos como en los otros layouts. El FlowPane tiene 4 constructores, el primero es vació, el segundo se pasa la orientación, el tercero recibe dos parámetros llamados hgap y vgap y el ultimo recibe la orientación y los hgap y vgap.
Entonces, si quisieramos hacer un FlowPane vertical seria asi:

public class FlowPaneTest extends Application {
    private FlowPane flow;
    @Override
    public void start(Stage stage)  {
        flow = new FlowPane(Orientation.VERTICAL);//Establecemos la orientación
        flow.getChildren().addAll(new Button("Boton 1"), new Button("Boton 2"), new Button("Boton 3"));
       
        Scene s = new Scene(flow);
        stage.setScene(s);
        stage.show();
    }
}

Quedando de la siguiente manera:

Si quisieramos agregar espacio entre los nodos, podemos hacerlo desde el constructor o setearlo desde el layout asi;

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

/**
 *
 * @author kalt
 */

public class FlowPaneTest extends Application {
    private FlowPane flow;
    @Override
    public void start(Stage stage)  {
        flow = new FlowPane(Orientation.VERTICAL);
        flow.setVgap(10);//Seteamos la separación vertical entre los nodos.
        flow.getChildren().addAll(new Button("Boton 1"), new Button("Boton 2"), new Button("Boton 3"));
       
        Scene s = new Scene(flow);
        stage.setScene(s);
        stage.show();
    }
}

El resultado es el siguiente:

Layout GridPane

Este layout nos permite crear una matriz/cuadricula, veamos un ejemplo simple de esto:

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

/**
 *
 * @author kalt
 */

public class GridPaneTest extends Application {
    private GridPane grid;
    @Override
    public void start(Stage stage)  {
        grid = new GridPane();
       
        grid.add(new Button("Posicion 0, 0"), 0, 0);
        grid.add(new Button("Posicion 0, 1"), 0, 1);
        grid.add(new Button("Posicion 0, 2"), 0, 2);
       
        Scene s = new Scene(grid);
        stage.setScene(s);
        stage.show();  
    }
}

Obtendremos como resultado lo siguiente:

Al igual que FlowPane, GridPane tambien tiene los metodos Hgap y Vgap para separar los nodos. Una simple linea hace la diferencia:

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

/**
 *
 * @author kalt
 */

public class GridPaneTest extends Application {
    private GridPane grid;
    @Override
    public void start(Stage stage)  {
        grid = new GridPane();
        grid.setVgap(10);
        grid.add(new Button("Posicion 0, 0"), 0, 0);
        grid.add(new Button("Posicion 0, 1"), 0, 1);
        grid.add(new Button("Posicion 0, 2"), 0, 2);
       
        Scene s = new Scene(grid);
        stage.setScene(s);
        stage.show();  
    }
}

Resultado:

Pero este layout no pareceria tan cool si no lo hicieramos mas complejo, veamos una verdadera matriz:

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

/**
 *
 * @author kalt
 */

public class GridPaneTest extends Application {
    private GridPane grid;
    @Override
    public void start(Stage stage)  {
        grid = new GridPane();
        grid.setVgap(10);
        grid.setHgap(10);
        grid.add(new Button("Posicion 0, 0"), 0, 0);
        grid.add(new Button("Posicion 1, 0"), 1, 0 );
        grid.add(new Button("Posicion 0, 1"), 0, 1);
        grid.add(new Button("Posicion 1, 1"), 1, 1);
        grid.add(new Button("Posicion 0, 2"), 0, 2);
        grid.add(new Button("Posicion 1, 2"), 1, 2);
       
        Scene s = new Scene(grid);
        stage.setScene(s);
        stage.show();  
    }
}

Recordemos, que los parametros que recibe el metodo add que usamos del layout GridPane recibe un nodo y las posiciones, donde primero es la columna y despues la fila.
Resultado:

Observamos tambien que agregamos el espacio horizontal.
Pero GridPane es mas potente de lo que parece y podemos hacer algo bastante util en algunos casos, colocar un nodo en un espacio sin relacion con los otros nodos, importandonos solamente su posicion.

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

/**
 *
 * @author kalt
 */

public class GridPaneTest extends Application {
    private GridPane grid;
    @Override
    public void start(Stage stage)  {
        grid = new GridPane();
        grid.setVgap(10);
        grid.setHgap(10);
        grid.add(new Button("Posicion 0, 0"), 0, 0);
        grid.add(new Button("Posicion 1, 0"), 1, 0 );
        grid.add(new Button("Posicion 0, 1"), 0, 1);
        grid.add(new Button("Posicion 1, 1"), 1, 1);
        grid.add(new Button("Posicion 0, 2"), 0, 2);
        grid.add(new Button("Posicion 1, 2"), 1, 2);
       
        grid.add(new Button("Posicion Col 9 Fila 2"), 9, 2);
       
        Scene s = new Scene(grid);
        stage.setScene(s);
        stage.show();  
    }
}

El resultado es el siguiente:

Layout StackPane

Estamos ante uno de los layouts un tanto peculiar, puesto que este agrega sus nodos en una pila, el primer elemento queda debajo del segundo y así sucesivamente. Veamos un ejemplo simple:

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

/**
 *
 * @author kalt
 */

public class StackPaneTest extends Application {
    private StackPane sp;
    @Override
    public void start(Stage stage)  {
        sp = new StackPane();
        sp.getChildren().addAll(new Button("Boton 1"), new Button("Botont 2"), new Button("Boton 3"));
       
        Scene s = new Scene(sp);
        stage.setScene(s);
        stage.show();
    }
}

Resultado:

Al parecer no tiene sentido, puesto que todo esta encimado pero, hay formas de colocar los nodos en diferentes posiciones. Aunque, antes de eso veamos otro ejemplo.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 *
 * @author kalt
 */

public class StackPaneTest extends Application {
    private StackPane sp;
    @Override
    public void start(Stage stage)  {
        sp = new StackPane();
        sp.setPadding(new Insets(15));
        sp.getChildren().addAll(new Rectangle(150, 150, Color.DARKBLUE),new Button("Boton 1"));
       
        Scene s = new Scene(sp);
        stage.setScene(s);
        stage.show();
    }
}


Hay que tener en cuenta que de manera predeterminada el StackPane coloca los nodos en el centro. Aunque eso se puede modificar:

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.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 *
 * @author kalt
 */

public class StackPaneTest extends Application {
    private StackPane sp;
    @Override
    public void start(Stage stage)  {
        sp = new StackPane();
        sp.setPadding(new Insets(15));
        sp.setAlignment(Pos.BOTTOM_RIGHT);//Simplemente asignamos la alineacion al objeto
        sp.getChildren().addAll(new Rectangle(150, 150, Color.DARKBLUE),new Button("Boton 1"));
       
        Scene s = new Scene(sp);
        stage.setScene(s);
        stage.show();
    }
}

Resultando:

Ahora veamos como colocar los nodos en diferentes posiciones:

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

/**
 *
 * @author kalt
 */

public class StackPaneTest extends Application {
    private StackPane sp;
    @Override
    public void start(Stage stage)  {
        sp = new StackPane();
        Button b1, b2, b3;
        b1 = new Button("Boton 1");
        b2 = new Button("Boton 2");
        b3 = new Button("Boton 3");
       
        StackPane.setAlignment(b1, Pos.CENTER);
        StackPane.setAlignment(b2, Pos.BOTTOM_CENTER);
        StackPane.setAlignment(b3, Pos.TOP_RIGHT);
        sp.getChildren().addAll(b1, b2, b3);
       
        Scene s = new Scene(sp);
        stage.setScene(s);
        stage.show();
    }
}

El resultado es:

TilePane

TilePane al igual que FlowPane crea un layout que permite añadir nodos de forma vertical o horizontal. La diferencia radica en que TilePane puede especificar en filas y columnas como se van añadiendo los nodos. Veamos un ejemplo.
Nota: Por defecto la posicion es horizontal al igual que FlowPane.

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

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author kalt
 */

public class TilePaneTest extends Application {
    private TilePane tile;
    @Override
    public void start(Stage stage) {
        tile = new TilePane();//Por defecto la posicion horizontal
        tile.setPrefColumns(6);//Declaramos 6 columnas
        tile.setPrefRows(4);//Y 4 filas
        for(int i = 0; i < 20; i++) {
            tile.getChildren().add(new Button("Boton "+ i));
        }
        Scene s = new Scene(tile);
        stage.setScene(s);
        stage.show();
    }
}

Resultado:

De manera vertical la cosa cambia, pero hay que tener en cuenta que las posiciones por los métodos setPrefColumns y setPrefRows no son definitivas, si tu cambias el tamaño de la ventana puedes obtener resultados que a simple vista parecen extraños pero solo hay que entender los métodos.

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author kalt
 */

public class TilePaneTest extends Application {
    private TilePane tile;
    @Override
    public void start(Stage stage) {
        tile = new TilePane(Orientation.VERTICAL);
        tile.setPrefColumns(6);
        tile.setPrefRows(4);
        for(int i = 0; i < 20; i++) {
            tile.getChildren().add(new Button("Boton "+ i));
        }
        Scene s = new Scene(tile);
        stage.setScene(s);
        stage.show();
    }
}

Resultado:

Layout AnchorPane

AnchorPane es parecido a BorderPane la diferencia radica en que AnchorPane nos brinda mas libertad para posicionar los elementos, veamos un ejemplo simple de esto:

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

/**
 *
 * @author kalt
 */

public class AnchorPaneTest extends Application {
    private AnchorPane anchor;
    @Override
    public void start(Stage stage)  {
        anchor  = new AnchorPane();

        Button b2  = new Button("Boton 2");
        Button b3 = new Button("Boton 3");
        AnchorPane.setTopAnchor(b2, 10.0);
        AnchorPane.setRightAnchor(b2, 10.0);
       
        AnchorPane.setBottomAnchor(b3, 20.0);
        AnchorPane.setLeftAnchor(b3, 20.0);
       
        anchor.getChildren().addAll(new Button("Boton 1"), b2, b3);
       
        Scene s = new Scene(anchor);
        stage.setScene(s);
        stage.show();
    }
}

Resultado:

Como podemos observar, se posicionan los nodos mediante los metodos estaticos de la clase AnchorPane y para agregarlos al layout se usar el metodo getChildren.add o addAll.

Con esto terminamos esta publicación, si leyeron todo, gracias y si no, también ;)
Cualquier duda la responderé según mis conocimientos y mi tiempo. Se aceptan criticas de cualquier tipo siempre y cuando sea para mejorar el contenido.

Saludos.

AdjuntoTamaño
anchorpane1.png4.46 KB
borderpane1.png4.21 KB
borderpane2.png6.53 KB
borderpaneresize.png5.12 KB
flowpane1.png2.79 KB
flowpane2.png3.59 KB
flowpane3.png3.62 KB
gridpane1.png3.19 KB
gridpane2.png3.29 KB
gridpane3.png3.99 KB
gridpane4.png7.7 KB
stackpane1.png2.69 KB
stackpane2.png2.9 KB
stackpane3.png6.53 KB
stackpane4.png3.72 KB
tilepane1.png9.54 KB
tilepane2.png9.81 KB
vbox2.png2.67 KB
vbox3.png3.1 KB
vbox_1.png3.29 KB

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">