FAQ JavaFXConsultez toutes les FAQ
Nombre d'auteurs : 4, nombre de questions : 507, dernière mise à jour : 2 novembre 2016 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum JavaFX de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Qu'est-ce qu'un contrôleur ?
- Comment déclarer un contrôleur dans un fichier FXML ?
- Comment accéder au contrôleur d'un fichier FXML ?
- Qu'est-ce que l'interface Initializable ?
- Comment injecter des ressources dans un contrôleur ?
- Comment accéder au contrôleur d'un fichier FXML inclus dans un autre fichier FXML ?
- Comment invoquer une méthode du contrôleur depuis le document FXML ?
- Comment injecter un contrôleur dans le document FXML ?
Un contrôleur est une classe externe au fichier FXML, généralement écrite en Java, qui est chargée par le chargeur FXML en même temps que le fichier FXML. Cette classe permet de manipuler les entités nommées décrites dans le fichier FXML, d'y accéder depuis le reste de votre application ou même de modifier le contenu de l'arborescence décrite dans le FXML.
Un contrôleur doit être déclaré dans une classe publique disposant du constructeur par défaut ou d'un constructeur public sans paramètre.
Par exemple :
Code Java : | Sélectionner tout |
1 2 | public class MyController { } |
Ce code définit un contrôleur vide.
Pour déclarer un contrôleur dans un fichier FXML, il faut ajouter l'attribut fx:controller sur l’élément racine du document FXML. Cet attribut doit contenir le chemin complet vers la classe servant de contrôleur pour ce FXML.
Par exemple :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/> |
Une exception sera levée lors du chargement du FXML si la classe n'est pas présente sur le CLASSPATH ou n'est pas accessible.
Pour accéder au contrôleur d'un fichier FXML, après chargement de ce fichier, il faut invoquer la méthode getController() du chargeur.
Par exemple, soit le fichier FXML suivant :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/> |
Pour accéder à son contrôleur, il suffit de faire :
Code Java : | Sélectionner tout |
1 2 3 4 | final URL fxmlURL = getClass().getResource("monFXML.fxml"); final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL); final Node node = fxmlLoader.load(); final TestController controler = fxmlLoader.getController(); |
L'interface javafx.fxml.Initializable est une interface optionnelle que votre contrôleur peut implémenter si besoin. Cette interface définit la méthode initialize() qui sera invoquée au chargement du FXML après l'injection des ressources du FXML dans le contrôleur.
Par exemple :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 | public class MyController implements Initializable { @Override public void initialize(URL location, ResourceBundle resources) { // Faire les initialisations avant affichage ici. } } |
Pour injecter des ressources dans un contrôleur, chaque ressource doit avoir, dans sa définition dans le fichier FXML, un nom unique déclaré avec l'attribut fx:id. Il vous faut ensuite déclarer des variables équivalentes, avec les types appropriés, dans le contrôleur en les annotant javafx.fxml.FXML (@FXML). Au chargement du FXML, les références des objets créés seront injectées dans le contrôleur.
Par exemple :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MyController"> <children> <Label fx:id="label"/> </children> </AnchorPane> |
Il est alors possible d'utiliser un contrôleur similaire au code suivant :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | public class MyController implements Initializable { @FXML private AnchorPane root; @FXML private Label label; @Override public void initialize(URL location, ResourceBundle resources) { // Faire les initialisations avant affichage ici. } } |
La méthode initialize() sera invoquée après l'injection des valeurs dans le contrôleur.
Si un élément dans le fichier FXML est déclaré avec un attribut fx:id qui n'a pas d’équivalent dans les variables annotées par @FXML dans le contrôleur, alors le nœud graphique ne sera pas directement accessible depuis le code du contrôleur.
Si le contrôleur dispose d'une variable annotée par @FXML qui n'a pas d’équivalent dans les éléments disposant d'attributs fx:id dans le fichier FXML, alors cette variable restera à la valeur null après injection.
Lorsqu'on inclut un fichier FXML (le fichier secondaire) dans un autre fichier FXML (le fichier principal), il est possible de lui donner également un attribut fx:id. Cette valeur permet de déclarer implicitement une référence vers le contrôleur du FXML inclus (le contrôleur secondaire) depuis le contrôleur du FXML maitre (le contrôleur principal).
Prenons ce simple fichier FXML qui sera le fichier secondaire, test.fxml :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/> |
Et disposant du contrôleur secondaire suivant :
Code Java : | Sélectionner tout |
1 2 | public class TestController { } |
Et incluons-le dans un autre FXML, le fichier principal, master.fxml :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MasterController"> <children> <fx:include fx:id="test" source="test.fxml"/> </children> </AnchorPane> |
Alors il est possible d'injecter implicitement une référence vers le contrôleur secondaire dans notre contrôleur principal en utilisant l'identifiant <identifiant du FXML secondaire>Controller. Par exemple :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 | public class MasterController{ // Le nœud racine de notre FXML secondaire sera injecté dans cette variable. @FXML private AnchorPane test; // Le contrôleur de notre FXML secondaire sera injecté dans cette variable. @FXML private TestController testController; } |
Il est possible d'invoquer une méthode du contrôleur depuis le document FXML, par exemple en réaction au clic d'un bouton, en spécifiant le nom de la méthode préfixé du caractère #.
Par exemple :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <StackPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MyController"> <children> <Button fx:id="button" onAction="#onButtonActivated"/> </children> </StackPane > |
Il faut ensuite déclarer la méthode dans le corps du contrôleur. On prendra soin d’annoter la méthode par @FXML.
Par exemple :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 | public class MyController { @FXML private void onButtonActivated() { System.out.println("Salut le monde !"); } } |
Il est également possible de définir une méthode recevant un paramètre de type ActionEvent :
Code Java : | Sélectionner tout |
1 2 3 4 | @FXML private void onButtonActivated(final ActionEvent actionEvent) { System.out.println("Salut le monde !"); } |
Dans le cas où deux méthodes seraient déclarées dans le contrôleur avec des noms identiques, c'est la méthode acceptant un paramètre de type ActionEvent qui sera invoquée en priorité.
Une exception sera levée au chargement du fichier FXML si aucune méthode portant ce nom n'est définie ou si elle n'est pas annotée par l'annotation @FXML.
Il est possible d'injecter un contrôleur dans un FXML qui n'en a pas de défini. Pour cela, il suffit d'invoquer la méthode setController() du chargeur FXMLLoader avant l'appel à sa méthode load().
Prenons le fichier FXML suivant :
Code XML : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <VBox id="VBox" spacing="10" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> <Button fx:id="button1" text="Button1" onAction="#handleButton1"/> <Button fx:id="button2" text="Button2" onAction="#handleButton2"/> <Button fx:id="button3" text="Button3" onAction="#handleButton3"/> <Button fx:id="button4" text="Button4" onAction="#handleButton4"/> <Button fx:id="button5" text="Button5" onAction="#handleButton5"/> </VBox> |
En temps normal, il n'est pas possible de charger ce fichier FXML. En effet, nous référençons des méthodes sur les propriétés onAction des boutons, mais n'avons nulle part de contrôleur dans lequel ces méthodes sont définies : une exception sera donc levée si nous essayons de le charger.
Prenons la classe suivante qui va nous servir de contrôleur :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public final class TestInjectionController implements Initializable { @FXML private Button button1; @FXML private Button button2; @FXML private Button button3; @FXML private Button button4; @FXML private Button button5; @Override public void initialize(URL location, ResourceBundle resources) { System.out.println("Initialize !"); } @FXML private void handleButton1() { System.out.println("Bouton 1"); } @FXML private void handleButton2() { System.out.println("Bouton 2"); } @FXML private void handleButton3() { System.out.println("Bouton 3"); } @FXML private void handleButton4() { System.out.println("Bouton 4"); } @FXML private void handleButton5() { System.out.println("Bouton 5"); } } |
Nous pouvons injecter cette classe en tant que contrôleur de notre fichier FXML en faisant :
Code Java : | Sélectionner tout |
1 2 3 4 | final URL fxmlURL = getClass().getResource("testinjection.fxml"); final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL); fxmlLoader.setController(new TestInjectionController()); final Node node = fxmlLoader.load(); |
Désormais, nous pouvons charger le FXML sans lever d'exception et notre contrôleur prend en charge les actions des boutons. Nous pouvons voir également que la méthode initialize() du contrôleur est correctement invoquée.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.