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 :
- Contrôles : éléments interactifs comme des boutons, des champs texte, etc.
- Formes : éléments graphiques comme des rectangles, des cercles, etc.
- Conteneurs : éléments qui contiennent d'autres nœuds et définissent leur arrangement
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 :
- Interfaces qui doivent s'adapter dynamiquement à la taille de la fenêtre
- Mise en page complexe avec positionnement précis des éléments
- Création de zones de contenu redimensionnables
- Interfaces où les éléments doivent maintenir une position relative entre eux
Démonstration visuelle des conteneurs
Cette image montre clairement les différents types de conteneurs JavaFX et comment ils organisent leurs éléments enfants :

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
- Imbrication de conteneurs : N'hésitez pas à imbriquer des conteneurs pour créer des mises en page complexes. Par exemple, un BorderPane comme conteneur principal avec des VBox dans ses différentes régions.
- Contraintes de taille : Utilisez
setPrefSize
,setMinSize
etsetMaxSize
pour contrôler la taille des conteneurs. - Alignement : La classe
javafx.geometry.Pos
permet de définir l'alignement dans les conteneurs avecsetAlignment(Pos.CENTER)
par exemple. - Espacement : N'oubliez pas d'utiliser
setPadding
etsetSpacing
pour améliorer la lisibilité. - Contraintes dans GridPane : Utilisez
GridPane.setColumnSpan
etGridPane.setRowSpan
pour qu'un élément occupe plusieurs cellules.