Tutoriel JavaFX (Français)

Partie 1 : le Scene Builder

Screenshot AddressApp Part 1

Sujets dans la partie 1

  • Faire connaissance avec JavaFX
  • Créer et démarrer un projet JavaFX
  • Utiliser le Scene Builder pour concevoir l’interface utilisateur
  • Structurer simplement une application en utilisant le modèle de conception modèle vue contrôleur

Prérequis

Configuration d’Eclipse

Nous devons paramètrer Eclipse pour qu’il utilise le JDK 8 et qu’il sache où trouver le le Scene Builder :

  1. Ouvrez les préférences et sélectionnez la partie Java | Installed JREs.

  2. Cliquez sur le bouton Add… pour ajoutez le JDK 8 puis sur Standard VM et sélectionnez le dossier contenant le JDK 8.

  3. Supprimez les autres JREs et JDKs afin que le JDK 8 devienne le JDK par défaut (default) !
    Preferences JDK

  4. Sélectionnez la partie Java | Compiler. Définissez la Compiler compliance level à 1.8 !
    Preferences Compliance

  5. Sélectionnez la partie JavaFX puis spécifiez le chemin de votre exécutable Scene Builder !
    Preferences JavaFX

Liens utiles

Peut-être voudrez-vous mettre les liens suivants dans vos favoris :

Maintenant, nous pouvons commencer !


Créer un nouveau projet JavaFX

Dans votre IDE Eclipse (avec e(fx)clipse installé), cliquez sur File | New | Other… et sélectionnez JavaFX Project.
Spécifiez le nom du projet (par exemple AddressApp) et cliquez sur Finish !

Supprimez le package application et son contenu s’il a été automatiquement créé !

Créer le packages

Dès maintenant nous allons suivre les bonnes pratiques de programmation. Un principe très important est le Model-View-Controller (MVC). En accord avec ceci, nous divisons notre code en trois unités. Nous allons créer un package pour chaques parties : (clic droit sur le dossier src, New… | Package):

  • ch.makery.address - contient la plupart des classes contrôleur ( = la logique métier)
  • ch.makery.address.model - contient les classe modèle
  • ch.makery.address.view - contient l’interface graphique

Note: Notre package view contiendra aussi quelques contrôleurs dépendant directement d’une interface graphique unique. Appelons-les view-controllers !


Créer le fichier de disposition FXML

Il y a deux manières de créer une interface utilisateur. L’une consiste à utiliser un fichier XML et l’autre est de tout programmer en Java. En cherchant sur le web, vous trouverez les deux. Nous utiliserons ici le fichier XML (extension .fxml) pour presque toutes les interfaces. Je trouve cette façon de faire plus propre car cela permet de mieux séparer les contrôleurs des interfaces. De plus, nous pouvons utiliser l’outil graphique Scene Builder pour modifier le XML. Cela signifie que nous n’aurons pas à travailler directement en XML.

Clic droit sur le package view et new FXML Document ! Nommez-le PersonOverview !

New FXML Document

New PersonOverview


Conception de la GUI avec Scene Builder

Note : si vous ne pouvez pas faire fonctionner Scene Builder, téléchargez la source de cette partie du tutoriel et essayez avec le fichier .fxml inclu !

Faites un clic droit sur PersonOverview.fxml et puis cliquez sur Open with Scene Builder. Maintenant vous devriez voir s’afficher le programme Scene Builder avec un AnchorPane (visible dans la partie hiérarchie sur la gauche).

(Si Scene Builder ne démarre pas, cliquez sur Window | Preferences | JavaFX et définissez le chemin correct relatif à l’installation de votre Scene Builder).

  1. Dans la partie Hierarchy, sélectionnez l’Anchor Pane et ajustez la taille sous Layout (dans la partie de droite):
    Anchor Pane Size

  2. Ajoutez un Split Pane (Horizontal Flow) en utilisant un drag et drop depuis la librairie sur gauche jusque dans la partie centrale ! Faites un clic droit dans la partie Hierarchy à gauche sur Split Pane et sélectionnez Fit to Parent (ajuster au contrôle parent) !
    Fit to Parent

  3. Faites glisser un TableView (depuis la liste Controls sur la gauche) et amenez-le dans la partie de gauche du SplitPane. Sélectionnez la TableView (pas la colonne mais le tableau) et définissez la contrainte du TableView comme suit. Dans un AnchorPane, vous pouvez toujours définir les ancres sur les quatres bords (plus d’information dans la partie relative aux Layouts).
    TableView Anchors

  4. Allez dans le menu Preview | Show Preview in Window pour voir si la fenêtre s’affiche comme vous le voulez. Essayez de la rediensionner ! Le TableView devrait être redimensionné en même temps que la fenêtre parce qu’il est ancré aux bordures.

  5. Modifiez l’entête des colonnes (dans les propriétés) ! Nommez-les “First Name” et “Last Name” !
    Column Texts

  6. Sélectionnez le TableView et définissez constrained-resize sous Column Resize Policy (dans les propriétés). Ceci spécifie que la colonne prendra tout l’espace disponible.
    Column Resize Policy

  7. Ajoutez un Label sur le côté droit dont le texte sera “Person Details” (suggestion : utilisez la recherche pour retrouver le Label). Ajustez le layout en utilisant les ancres. Person Details Label

  8. Ajoutez un GridPane sur le côté droit, sélectionnez-le puis ajuster son layout en utilisant les ancres (top, right et left) !
    GridPane Layout

  9. Ajoutez le étiquettes suivantes dans les cellules !
    Note : pour ajouter une ligne dans le GridPane, sélectionnez l’index d’un ligne existante (elle deviendra jaune) puis faites un clic droit sur l’index et sélectionnez “Add Row”.
    Add labels

  10. Ajoutez une ButtonBar en bas ! Ajoutez trois boutons à la barre ! Enfin, définissez les ancres pour qu’ils restent à leur place soit en bas et à droite.
    Button Group

  11. Maintenant, vous devriez voir quelque chose ressemblant à l’image ci-dessous. Utilisez le menu Preview pour tester le comportement après redimensionnement.
    Preview


Créer l’application principale

Vous avez besoin d’un autre fichier FXML pour la disposition de base. Celle-ci contiendra une barre de menu et encapsulera le PersonOverview.fxml que nous venons de créer.

  1. Créez un autre FXML Document dans le package view appelé RootLayout.fxml. Cette fois, choisissez BorderPane comme élément racine.
    New RootLayout

  2. Ouvrez le fichier RootLayout.fxml dans l’application Scene Builder !

  3. Redimensionnez le BorderPane de sorte que la largeur préférée (Pref Width) soit à 600 et la hauteur préférée (Pref Height) à 400.
    RootLayout Size

  4. Ajoutez une MenuBar dans le slot supérieure (TOP). Nous n’implémenterons pas les fonctionnalités du menu pour l’instant.
    MenuBar

La classe principale de JavaFX

Maintenant vous devez créer la classe principale (main java class) qui démarrera notre application avec le fichier RootLayout.fxml et ajoutera la PersonOverview.fxml au centre.

  1. Faites un clic droit dans votre projet puis cliquez sur New | Other… et enfin sur JavaFX Main Class.
    New JavaFX Main Class

  2. Nous nommerons la classe MainApp et nous la placerons dans le package contrôleur ch.makery.address (note : c’est le package parent des sous-paquets view et model).
    New JavaFX Main Class

La classe MainApp.java générée hérite de la classe Application et contient deux méthodes. C’est la structure basique dont nous avons besoin pour démarrer une application JavaFX. La partie la plus importante pour nous est la méthode start(Stage primaryStage). Cette méthode est automatiquement appelée lors du lancement de l’application (launch) avec la méthode main.

Comme vous le voyez, la méthode start(...) reçoit un objet Stage aen paramètre. Le diagramme suivant montre la structure de toutes les applications JavaFX :

New FXML Document
Image provenant de : http://www.oracle.com

C’est comme une pièce de théâtre : l’objet Stage est le conteneur principal qui est habituellement une fenêtre avec des bordures et qui a les boutons habituels pour minimiser, maximiser et fermer. Dans le Stage, vous ajoutez une Scene qui peut, bien sûr, être échangée avec un autre object Scene. Sont ajoutés dans la Scene les noeuds JavaFX actuels comme AnchorPane, TextBox, etc.

Pour plus d’informations à ce sujet, voir Working with the JavaFX Scene Graph.


Ouvrez MainApp.java et remplacez le code par celui-ci :

package ch.makery.address;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class MainApp extends Application {

    private Stage primaryStage;
    private BorderPane rootLayout;

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("AddressApp");

        initRootLayout();

        showPersonOverview();
    }
    
    /**
     * Initializes the root layout.
     */
    public void initRootLayout() {
        try {
            // Load root layout from fxml file.
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
            rootLayout = (BorderPane) loader.load();
            
            // Show the scene containing the root layout.
            Scene scene = new Scene(rootLayout);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Shows the person overview inside the root layout.
     */
    public void showPersonOverview() {
        try {
            // Load person overview.
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml"));
            AnchorPane personOverview = (AnchorPane) loader.load();
            
            // Set person overview into the center of root layout.
            rootLayout.setCenter(personOverview);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
	/**
	 * Returns the main stage.
	 * @return
	 */
	public Stage getPrimaryStage() {
		return primaryStage;
	}

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

Les commentaires épars devraient vous donner quelques indices concernant ce qu’il se passe.

Si vous exécutez l’application maintenant, vous devriez voir quelque chose ressemblant à la capture d'écran figurant au début de ce post.

Problèmes fréquents

Lorsque JavaFX ne peut pas trouver le fichier fxml que vous avez spécifié, vous devriez voir le message d’erreur suivant :

java.lang.IllegalStateException: Location is not set.

Pour résoudre ce problème, vérifiez une seconde fois le chemin du fichier fxml !

Si cela ne fonctionne toujours pas, téléchargez la source de cette partie du tutoriel et essayez avec le fichier fxml inclu !

Qu’est-ce qui suit ?

Dans la partie 2 du tutoriel, vous allez ajouter des données et des fonctionnalités à notre AddressApp.

Voici quelques autres articles qui pourraient vous intéresser :