Notes S9

1. Introduction

Java propose trois bibliothèques pour créer des interfaces graphiques (GUI) : AWT (obsolète), Swing (en remplacement) et JavaFX (la plus moderne). Ce cours présente JavaFX, dont les concepts se retrouvent dans la plupart des bibliothèques graphiques modernes.

2. Concepts fondamentaux : le graphe de scène

Une interface JavaFX est constituée de nœuds (nodes) organisés hiérarchiquement dans un graphe de scène (scene graph) — qui est en réalité un arbre. Cette hiérarchie reflète l’imbrication visuelle à l’écran.

On distingue trois catégories de nœuds :

  • Nœuds de base (feuilles) : entités atomiques comme des formes ou boutons
  • Nœuds intermédiaires : conteneurs organisant leurs enfants (souvent des panneaux)
  • Racine : toujours de type Scene, sans représentation graphique propre

Pour s’afficher, l’objet Scene doit être placé dans un objet Stage, qui représente typiquement une fenêtre du système d’exploitation.

Exemple type d’un formulaire de connexion :

Label nameL = new Label("Nom :");
TextField nameF = new TextField();
Button connectB = new Button("Connexion");
 
GridPane grid = new GridPane();
grid.addRow(0, nameL, nameF);
grid.addRow(1, pwL, pwF);
grid.add(connectB, 0, 2, 2, 1);
 
Scene scene = new Scene(grid);

3. Les types de nœuds

Tous les nœuds héritent de la classe Node, qui permet de les positionner, styliser et y attacher des gestionnaires d’événements.

Nœuds géométriques (héritent de Shape)

Formes simples (Circle, Line, Rectangle…), courbes de Bézier, chemins (Path) et texte (Text).

Nœuds graphiques

  • ImageView : affichage d’images
  • MediaView : affichage de vidéos
  • Canvas : surface de dessin modifiable

⚠️ Différence clé : un nœud géométrique existe dans le graphe et peut être manipulé individuellement (modèle vectoriel), alors qu’un dessin sur Canvas est figé une fois tracé (modèle bitmap).

Nœuds de contrôle (héritent de Control)

Informationnels (passifs) : Label, ProgressIndicator, ProgressBar

Boutons :

  • Button : un seul état (action)
  • ToggleButton : deux états (activé/désactivé)
  • RadioButton : appartient à un groupe, un seul activable à la fois

Éditeurs de valeurs atomiques : TextField, TextArea, HTMLEditor, Slider, Spinner, ChoiceBox, ColorPicker, DatePicker

Éditeurs de valeurs composites : ListView, TableView, TreeView

Panneaux (sous-classes de Pane)

Conteneurs qui organisent leurs enfants spatialement. Pour gérer le redimensionnement, ils utilisent les méthodes min/max/prefWidth et min/max/prefHeight des nœuds enfants.

PanneauOrganisation
PaneAucune (placement manuel)
BorderPane5 zones : centre + 4 latérales
GridPaneGrille de cases
StackPaneEmpilement (nécessite transparence)
ScrollPaneDéfilement d’un nœud trop grand
TabPaneOnglets (un visible à la fois)
SplitPaneDivision redimensionnable

4. Propriétés et liens

Problématique : synchroniser le modèle et l’interface graphique. JavaFX résout ce problème via le patron Observer, en renommant les concepts : sujetobservable, observateurauditeur (listener).

Propriétés

Une propriété est une cellule observable (un objet contenant une valeur observable), accessible en lecture seule ou en lecture/écriture.

ObjectProperty<String> p = new SimpleObjectProperty<>();
p.addListener((o, oV, nV) -> System.out.println(nV));
p.set("hello");  // affiche "hello"

Collections observables

Pour stocker plusieurs valeurs observables, le paquetage javafx.collections fournit ObservableList (extension de List) et FXCollections. Avantage : les notifications sont groupées (par exemple, un sort() ne notifie qu’à la fin du tri).

JavaFX beans

Convention pour des classes dont tous les attributs sont des propriétés :

  • méthode xxxProperty() pour accéder à la propriété
  • méthode getXxx() (ou isXxx() pour les booléens) pour la valeur
  • méthode setXxx() si la propriété est modifiable

La quasi-totalité des classes JavaFX sont des beans.

Liens de données (data binding)

Lien unidirectionnel simple (bind) : la propriété cible suit toujours la source. La cible ne peut plus être modifiée directement.

p1.bind(p2);  // p1 suit p2

Lien unidirectionnel complexe : permet d’exprimer des relations, par exemple le périmètre d’un cercle :

DoubleProperty r = new SimpleDoubleProperty();
DoubleBinding p = r.multiply(2d * Math.PI);

Lien bidirectionnel (bindBidirectional) : les deux propriétés se synchronisent mutuellement. Idéal pour un composant graphique qui affiche et modifie une valeur du modèle.

5. Gestion des événements

Un programme graphique fonctionne en programmation événementielle : il attend un événement, y réagit, recommence. Au cœur, une boucle événementielle :

tant que le programme n'est pas terminé attendre le prochain événement traiter cet événement

Spécificités JavaFX

JavaFX exécute la boucle dans un fil séparé : le JavaFX Application Thread. Conséquences importantes :

  • Toute manipulation d’un nœud déjà attaché à une Scene doit se faire depuis ce fil
  • Toute création de Scene ou Stage doit aussi s’y faire
  • Les gestionnaires doivent s’exécuter rapidement, sinon l’interface se bloque

Structure typique d’une application

public final class JavaFXApp extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        Button button = new Button("click me!");
        button.setOnAction(e -> System.out.println("click"));
        Scene scene = new Scene(button);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
  • main s’exécute sur le fil de lancement (launcher thread)
  • launch() démarre le fil d’application JavaFX
  • start() est appelé sur ce fil → c’est là qu’on construit l’interface

Types d’événements

Les gestionnaires implémentent l’interface fonctionnelle EventHandler<T>. JavaFX définit de nombreux événements :

  • Souris : clic, déplacement, survol
  • Tactile : appui, glissement
  • Clavier : pression, relâchement de touches
  • Spécifiques aux composants : pression d’un bouton, sélection, etc.

Points clés à retenir

  1. Architecture en arbre : StageScene → arbre de Node
  2. Trois familles de nœuds : géométriques, de contrôle, panneaux (conteneurs)
  3. Propriétés observables au cœur du système, permettant la synchronisation modèle ↔ vue
  4. Liens de données : bind (unidirectionnel), bindBidirectional (bidirectionnel) — alternative concise aux listeners manuels
  5. Concurrence : tout ce qui touche à l’interface doit s’exécuter sur le JavaFX Application Thread, et les gestionnaires doivent être rapides pour ne pas bloquer l’interface
  6. JavaFX beans : convention permettant à toute classe d’exposer ses attributs comme propriétés observables, facilitant l’intégration avec les composants graphiques