2016-07-06 1 views
0

Je travaille sur un projet qui nécessite une représentation "tablée" des VBox. Ma disposition hiérarchique de l'application est GridPane -> VBox (dans l'une des cellules) -> VBoxes (qui affichent différents ensembles de données les uns sur les autres) -> Data. J'ai deux scènes. Les données sont affichées sur la scène 1. L'utilisateur peut ajouter des données via un formulaire et en cliquant sur un bouton de la scène 2. Ensuite, les données ajoutées doivent être affichées sous les données existantes sous la forme d'une VBox dans la VBox parent sur scène 1 encore une fois.JavaFX: La VBox ajoutée dynamiquement n'apparaît pas

Voici le code qui fera clairement:

My Scene 1 fichier .fxml regarde les éléments suivants (simplifié):

<GridPane fx:id="grid" fx:controller="application.Controller"> 
    [here: ColumnConstraints] 
    <children> 
    <VBox fx:id="parentBox" GridPane.columnIndex="0" GridPane.rowIndex="1"/> 
    <Button fx:id="goToScene2" text="+" onAction="#goToScene2"/> 
    </children> 
</GridPane> 

Scène 2 a juste un bouton et un champ de texte:

<GridPane fx:id="grid" fx:controller="application.AddDataController"> 
    [here: ColumnConstraints] 
    <children> 
    <Button fx:id="addData" text="add" onAction="#bAddData"/> 
    <TextField fx:id="data"/> 
    </children> 
</GridPane> 

Mon contrôleur Scène 1 (contrôleur) ressemble à ceci:

public class Controller implements Initializable { 
    @FXML Button goToScene2; 
    @FXML VBox parentBox; 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
    } 

    public void addData(String s) { 
    Label lbl = new Label(s); 
    VBox dataBox = new VBox(); 
    dataBox.setPadding(new Insets(15, 5, 15, 5)); 
    dataBox.setSpacing(5); 
    dataBox.setMaxHeight(80); 
    dataBox.getChildren().add(lbl); 
    parentBox.getChildren().add(dataBox); 
    } 
} 

Cela a été conçu car la dataBox contient plus d'éléments que l'étiquette, mais cela ne me semble pas pertinent dans ce contexte.

My Scene 2 contrôleur (addDataController) ressemble à ceci:

@FXML Button addData; 
@FXML TextField data; 

@FXML protected void bAddData(){ 
    String content = data.getText();  
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    Pane p = fxmlLoader.load(getClass().getResource("scn1.fxml").openStream()); 
    Controller cont = (Controller) fxmlLoader.getController(); 

    cont.addData(content); 
} 

Ainsi, lorsque l'on clique sur Add-données-Bouton en Scène 2, la méthode déclenchée transmet les données saisies au contrôleur de scène 1. C'est parce que les nouvelles données devraient être affichées dans la scène 1 maintenant.

je me sens comme la logique ne fonctionne pas (édité ici), parce que quand je demande

System.out.println(parentBox.getChildren().size(); 

avant et après que les données ont été ajoutés, il a toujours un seul enfant, même si elle devrait avoir un more ...

Si je remplis artificiellement un String-Array et déplace tout depuis addData vers (String s) vers Initialize (...), cela fonctionne et les données apparaissent sous forme de VBox dans le VBox parent.

Je n'ai pas publié de classe principale, car le chargement des contrôleurs et le changement de scène ne posent aucun problème.

Merci beaucoup à tous pour votre aide! :)

+1

Je ne crois pas que l'instance 'Controller const' que vous utilisez pour appeler' AddData (content) 'avec est la même instance de' Controller' que votre 'Scene' principale utilise. Le 'FXMLLoader' crée une nouvelle instance qui n'est pas dans le graphe de scène. Une solution simple peut être de passer le contrôleur de scène principal à la deuxième scène. À quoi ressemble votre méthode 'goToScene'? – OttPrime

+0

C'est en fait quelque chose que je n'ai pas vu de cette façon. Cependant, le contrôleur utilisé est défini dans le fichier .fxml, donc je ne peux pas y accéder à partir d'une autre classe. Il n'a jamais été chargé dans le code JavaFX. Rendre les classes de contrôleur statiques n'a pas fonctionné non plus. – s4inz

+0

Désolé pour ça. La méthode 'goToScene' appelle une méthode dans la classe de programme principale et transmet une chaîne. Cette chaîne est gérée dans une instruction switch-case et déclenche 'currentStage.setScene (newScene)'. – s4inz

Répondre

0

Juste pour fournir des informations plus détaillées, avec une idée, que je ne sais pas comment mettre en œuvre.

Ceci est ma classe principale:

@Override 
public void start(Stage primaryStage) { 
    currentStage = primaryStage; 
    Parent root = FXMLLoader.load(getClass().getResource("Scene1.fxml")); 
    scene1 = new Scene(root); 
} 

ce que je pourrais charger le contrôleur à ce point et faire un getter qui passe le contrôleur? Donc, je n'aurais qu'une seule instance tout au long du programme.

J'ai essayé encartage:

FXMLLoader fxmlLoader = new FXMLLoader(); 
fxmlLoader.load(getClass().getResource("Scene1.fxml").openStream()); 
Controller controller = (Controller) fxmlLoader.getController(); 

après la ligne

Parent root ... 

. Mais cela charge le fichier .xml deux fois. Comment puis-je bien connecter les deux parties?

Merci beaucoup pour votre patience!

EDIT ::::::::: Le code suivant a fonctionné pour moi:

@Override 
public void start(Stage primaryStage) { 
    currentStage = primaryStage; 
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Scene1.fxml")); 
    Parent root =(Parent) fxmlLoader.load(); 
    controller = (Controller) fxmlLoader.getController(); 
} 

Maintenant, je peux demander à la classe principale pour controller et il passe toujours cette instance unique.

Merci de m'avoir indiqué la bonne direction! :)