Les conteneurs JavaFX

Les conteneurs sont des éléments fondamentaux de JavaFX qui permettent d'organiser et d'arranger les composants graphiques dans l'interface utilisateur. Ils gèrent l'emplacement, la taille et l'organisation des contrôles qu'ils contiennent.

Rappel : le graphe de scène

Dans JavaFX, tous les éléments graphiques sont organisés en une structure hiérarchique appelée graphe de scène (Scene Graph). Ce graphe est composé de nœuds (Nodes) qui peuvent être :

Les conteneurs sont donc les éléments structurants de l'interface graphique.

# Structure typique d'un graphe de scène
Stage (fenêtre)
  └─ Scene (conteneur racine)
     └─ BorderPane (conteneur principal)
        ├─ MenuBar (en haut)
        ├─ VBox (à gauche - navigation)
        │  ├─ Button
        │  ├─ Button
        │  └─ Button
        ├─ TabPane (au centre - contenu principal)
        │  ├─ Tab
        │  │  └─ GridPane (formulaire)
        │  │     ├─ Label + TextField
        │  │     ├─ Label + TextField
        │  │     └─ Button
        │  └─ Tab
        └─ HBox (en bas - barre d'état)
           ├─ Label
           └─ ProgressBar

VBox et HBox

Les conteneurs VBox et HBox sont parmi les plus simples et les plus utilisés. Ils arrangent leurs enfants en une ligne verticale (VBox) ou horizontale (HBox).

VBox

Le conteneur VBox empile les éléments verticalement, de haut en bas.

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

public class VBoxExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création d'un VBox
        VBox vbox = new VBox();
        
        // Configuration des marges et espacement
        vbox.setPadding(new Insets(10));  // Marges extérieures
        vbox.setSpacing(8);               // Espace entre les éléments
        
        // Ajout des contrôles
        Label nameLabel = new Label("Nom :");
        TextField nameField = new TextField();
        Button submitButton = new Button("Valider");
        
        // Ajout des contrôles au VBox
        vbox.getChildren().addAll(nameLabel, nameField, submitButton);
        
        // Configuration de la scène
        Scene scene = new Scene(vbox, 300, 150);
        primaryStage.setTitle("Exemple VBox");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/VBoxExample.java

HBox

Le conteneur HBox aligne les éléments horizontalement, de gauche à droite.

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

public class HBoxExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création d'un HBox
        HBox hbox = new HBox();
        
        // Configuration des marges et espacement
        hbox.setPadding(new Insets(10));  // Marges extérieures
        hbox.setSpacing(10);              // Espace entre les éléments
        
        // Création de boutons
        Button button1 = new Button("Bouton 1");
        Button button2 = new Button("Bouton 2");
        Button button3 = new Button("Bouton 3");
        
        // Ajout des boutons au HBox
        hbox.getChildren().addAll(button1, button2, button3);
        
        // Configuration de la scène
        Scene scene = new Scene(hbox, 300, 80);
        primaryStage.setTitle("Exemple HBox");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/HBoxExample.java

Exemple équivalent en FXML

Voici comment définir un VBox en FXML :

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>

<VBox spacing="8.0" xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.example.javafxdemo.VBoxController">
    <padding>
        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
    <children>
        <Label text="Nom :" />
        <TextField fx:id="nameField" />
        <Button text="Valider" onAction="#handleSubmit" />
    </children>
</VBox>

Ce code va dans src/main/resources/com/example/javafxdemo/vbox-example.fxml

BorderPane

Le BorderPane divise l'espace en cinq zones : TOP, BOTTOM, LEFT, RIGHT et CENTER. C'est idéal pour créer des mises en page classiques d'application avec menu, barre latérale et zone de contenu principale.

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

public class BorderPaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création du BorderPane
        BorderPane borderPane = new BorderPane();
        
        // En-tête (TOP)
        Label headerLabel = new Label("Application JavaFX");
        headerLabel.setStyle("-fx-font-size: 20px; -fx-padding: 10px;");
        borderPane.setTop(headerLabel);
        
        // Barre latérale (LEFT)
        VBox sidebar = new VBox(10);
        sidebar.setPrefWidth(100);
        sidebar.getChildren().addAll(
            new Button("Accueil"),
            new Button("Profil"),
            new Button("Messages"),
            new Button("Paramètres")
        );
        borderPane.setLeft(sidebar);
        
        // Contenu principal (CENTER)
        TextArea mainContent = new TextArea();
        mainContent.setText("Zone de contenu principal");
        borderPane.setCenter(mainContent);
        
        // Barre d'état (BOTTOM)
        HBox statusBar = new HBox();
        statusBar.getChildren().add(new Label("Connecté | Version 1.0"));
        borderPane.setBottom(statusBar);
        
        // Panneau secondaire (RIGHT) - optionnel
        VBox rightPanel = new VBox(10);
        rightPanel.setPrefWidth(120);
        rightPanel.getChildren().addAll(
            new Label("Utilisateurs en ligne"),
            new Label("- Alice"),
            new Label("- Bob"),
            new Label("- Charlie")
        );
        borderPane.setRight(rightPanel);
        
        // Configuration de la scène
        Scene scene = new Scene(borderPane, 600, 400);
        primaryStage.setTitle("Exemple BorderPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/BorderPaneExample.java

GridPane

Le GridPane organise ses enfants dans une grille flexible de lignes et de colonnes. C'est idéal pour les formulaires et les interfaces tabulaires.

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

public class GridPaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création du GridPane
        GridPane grid = new GridPane();
        grid.setPadding(new Insets(20));
        grid.setHgap(10); // Espacement horizontal
        grid.setVgap(10); // Espacement vertical
        
        // Ajout des contrôles avec leurs coordonnées (col, row)
        grid.add(new Label("Nom d'utilisateur:"), 0, 0);
        grid.add(new TextField(), 1, 0);
        
        grid.add(new Label("Mot de passe:"), 0, 1);
        grid.add(new PasswordField(), 1, 1);
        
        grid.add(new Label("Email:"), 0, 2);
        grid.add(new TextField(), 1, 2);
        
        grid.add(new Label("Téléphone:"), 0, 3);
        grid.add(new TextField(), 1, 3);
        
        Button submitButton = new Button("S'inscrire");
        // Placement du bouton à la colonne 1, ligne 4, s'étend sur 1 col, 1 row
        grid.add(submitButton, 1, 4);
        
        // Configuration de la scène
        Scene scene = new Scene(grid, 350, 250);
        primaryStage.setTitle("Exemple GridPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/GridPaneExample.java

Autres conteneurs

FlowPane

Le FlowPane dispose les éléments les uns à côté des autres, puis passe à la ligne suivante lorsqu'il n'y a plus de place (comme un texte qui fait un retour à la ligne).

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

public class FlowPaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création du FlowPane
        FlowPane flow = new FlowPane();
        flow.setPadding(new Insets(10));
        flow.setHgap(10);
        flow.setVgap(10);
        
        // Ajout de plusieurs boutons
        for (int i = 1; i <= 15; i++) {
            flow.getChildren().add(new Button("Bouton " + i));
        }
        
        // Configuration de la scène
        Scene scene = new Scene(flow, 300, 250);
        primaryStage.setTitle("Exemple FlowPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/FlowPaneExample.java

TilePane

Le TilePane est similaire au FlowPane, mais tous les éléments ont la même taille, créant une grille uniforme.

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

public class TilePaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création du TilePane
        TilePane tile = new TilePane();
        tile.setPadding(new Insets(10));
        tile.setHgap(10);
        tile.setVgap(10);
        tile.setPrefColumns(4); // Nombre de colonnes préféré
        
        // Ajout de plusieurs boutons
        for (int i = 1; i <= 12; i++) {
            Button btn = new Button("Bouton " + i);
            // Chaque bouton a la même taille
            btn.setPrefWidth(100);
            btn.setPrefHeight(100);
            tile.getChildren().add(btn);
        }
        
        // Configuration de la scène
        Scene scene = new Scene(tile, 500, 400);
        primaryStage.setTitle("Exemple TilePane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/TilePaneExample.java

StackPane

Le StackPane empile les éléments les uns sur les autres, comme des couches. Utile pour superposer des éléments ou créer des overlays.

import javafx.application.Application;
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;

public class StackPaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création du StackPane
        StackPane stack = new StackPane();
        
        // Création d'un rectangle de fond
        Rectangle rect = new Rectangle(300, 200);
        rect.setFill(Color.LIGHTBLUE);
        
        // Création d'un bouton qui sera au-dessus du rectangle
        Button button = new Button("Cliquez-moi");
        
        // Ajout des éléments au StackPane (l'ordre d'ajout détermine l'ordre d'empilement)
        stack.getChildren().addAll(rect, button);
        
        // Configuration de la scène
        Scene scene = new Scene(stack, 300, 200);
        primaryStage.setTitle("Exemple StackPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/StackPaneExample.java

AnchorPane

L'AnchorPane permet d'ancrer les éléments enfants aux bords du conteneur ou entre eux, avec des distances spécifiques. C'est particulièrement utile pour créer des mises en page complexes qui doivent s'adapter à différentes tailles de fenêtre.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class AnchorPaneExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Création de l'AnchorPane
        AnchorPane anchorPane = new AnchorPane();
        anchorPane.setPadding(new Insets(10));
        
        // Création des contrôles
        Label titleLabel = new Label("Éditeur de notes");
        titleLabel.setStyle("-fx-font-size: 18px; -fx-font-weight: bold;");
        
        TextArea textArea = new TextArea();
        textArea.setPromptText("Écrivez votre texte ici...");
        
        Button saveButton = new Button("Enregistrer");
        Button cancelButton = new Button("Annuler");
        
        // Ajout des contrôles à l'AnchorPane
        anchorPane.getChildren().addAll(titleLabel, textArea, saveButton, cancelButton);
        
        // Configuration des ancrages
        
        // Titre ancré en haut à gauche
        AnchorPane.setTopAnchor(titleLabel, 10.0);
        AnchorPane.setLeftAnchor(titleLabel, 10.0);
        
        // Zone de texte ancrée aux quatre côtés avec marge
        AnchorPane.setTopAnchor(textArea, 40.0);
        AnchorPane.setLeftAnchor(textArea, 10.0);
        AnchorPane.setRightAnchor(textArea, 10.0);
        AnchorPane.setBottomAnchor(textArea, 50.0);
        
        // Boutons ancrés en bas à droite
        AnchorPane.setBottomAnchor(saveButton, 10.0);
        AnchorPane.setRightAnchor(saveButton, 10.0);
        
        AnchorPane.setBottomAnchor(cancelButton, 10.0);
        AnchorPane.setRightAnchor(cancelButton, 100.0);
        
        // Configuration de la scène
        Scene scene = new Scene(anchorPane, 500, 400);
        primaryStage.setTitle("Exemple AnchorPane");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Ce code va dans src/main/java/com/example/javafxdemo/AnchorPaneExample.java

L'AnchorPane est idéal pour :

Démonstration visuelle des conteneurs

Cette image montre clairement les différents types de conteneurs JavaFX et comment ils organisent leurs éléments enfants :

Types de conteneurs JavaFX

VBox

Empile les éléments verticalement, de haut en bas. Parfait pour les formulaires et les listes d'éléments.

HBox

Aligne les éléments horizontalement, de gauche à droite. Utile pour les barres d'outils, menus et alignements de contrôles.

GridPane

Organise les éléments dans une grille de lignes et colonnes. Idéal pour les formulaires et les interfaces tabulaires.

BorderPane

Divise l'espace en 5 zones : TOP, LEFT, CENTER, RIGHT et BOTTOM. Idéal pour les applications classiques avec menu, barre latérale et zone de contenu principale.

StackPane

Empile les éléments les uns sur les autres. Parfait pour les superpositions et les overlays.

FlowPane

Place les éléments les uns à côté des autres et passe à la ligne quand il n'y a plus de place. Similaire au comportement d'un texte.

TilePane

Similaire à FlowPane, mais tous les éléments ont la même taille, créant une grille uniforme. Parfait pour les galeries d'images.

AnchorPane

Permet d'ancrer les éléments enfants aux bords du conteneur ou entre eux, avec des distances spécifiques. Utile pour des mises en page complexes.

Conseils pratiques