2017-05-25 5 views
0

Supposons que j'ai deux fichiers FXML: principal et celui avec le composant personnalisé. Je veux avoir accès aux principaux composants de fichier du contrôleur personnalisé, comme celui-ci:Comment accéder aux composants de différents contrôleurs de fichiers?

Main.fxml:

<FlowPane> 
    <children> 
     <TextField fx:id="source" /> 
     <CustomBox fx:id="cbox" /> 
    </children> 
</FlowPane> 

Custom.fxml:

<fx:root type="HBox"> 
    <children> 
     <Button fx:id="showButton" onAction="#show" text="Show" /> 
    </children> 
</fx:root> 

CustomBox.java:

public class CustomBox extends HBox { 
    @FXML 
    private TextField source; 

    public CustomBox() { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("Custom.fxml")); 
     loader.setRoot(this); 
     loader.setController(this); 
     try { 
      loader.load(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    @FXML 
    protected void show() { 
     System.out.println(source.getText()); 
    } 
} 

Mais la méthode show() me donne NPE. Comment puis-je lier des composants et des contrôleurs à partir de différents fichiers?

+0

Vous ne pouvez pas injecter des contrôles définis dans un fichier FXML dans le contrôleur pour un autre fichier FXML - et en général c'est une mauvaise pratique d'exposer les contrôles en dehors du contrôleur pour le FXML dans lequel ils sont définis. Au lieu de cela, passez une référence au contrôleur principal au composant personnalisé et appelez une méthode sur le contrôleur principal pour extraire le texte (ou utilisez une approche MVC et définissez une classe de modèle et partagez une instance du modèle avec les deux contrôleurs). –

Répondre

0

Vous pouvez définir un contrôleur pour le principal fichier FXML, et d'exposer le texte de celle-ci:

public class MainController { 

    @FXML 
    private TextField source ; 

    @FXML 
    private CustomBox cbox ; 

    public String getText() { 
     return source.getText(); 
    } 

    @FXML 
    protected void initialize() { 
     cbox.setMainController(this); 
    } 
} 

et bien sûr préciser comme la classe du contrôleur dans le fichier Main.fxml

<FlowPane fx:controller="my.package.MainController"> 
    <children> 
     <TextField fx:id="source" /> 
     <CustomBox fx:id="cbox" /> 
    </children> 
</FlowPane> 

Ensuite, modifier votre CustomBox comme

public class CustomBox extends HBox { 

    private MainController mainController ; 

    public CustomBox() { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("Custom.fxml")); 
     loader.setRoot(this); 
     loader.setController(this); 
     try { 
      loader.load(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void setMainController(MainController mainController) { 
     this.mainController = mainController ; 
    } 

    public MainController getMainController() { 
     return mainController ; 
    } 

    @FXML 
    protected void show() { 
     System.out.println(mainController.getText()); 
    } 
} 

Je n'ai pas teste d, mais vous pourriez être en mesure de spécifier le contrôleur principal dans le fichier FXML:

<FlowPane fx:controller="my.package.MainController"> 
    <children> 
     <TextField fx:id="source" /> 
     <CustomBox fx:id="cbox" mainController="$controller" /> 
    </children> 
</FlowPane> 

puis omettre la méthode initialize() dans le MainController:

public class MainController { 

    @FXML 
    private TextField source ; 

    public String getText() { 
     return source.getText(); 
    } 

} 
+0

Merci, j'ai compris l'idée. –