1

Okay, I re-edited this question with a much easier smaller example.

My question is though, I have a StackPane, myStackPane that I am trying to load the Label onto. When the program first runs, the StackPane is empty. When I click on the handleButtonAction button it takes me to another stage so I can enter in the text I want on the label. When that new text is saved, it passes the new settings back to the main controller and updates the text of the label. It then adds the label to the StackPane.

However.... It's not displaying the new label in the stackpane. I know I am getting into the method and the variable is being passed correctly since I can System.out.println everything and it's all appropriate. But why will it not add it to the StackPane?

Thanks everyone!

Problems.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Problems extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

FXMLDocumentController

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class FXMLDocumentController implements Initializable {

    @FXML
    private Button button;
    @FXML
    private StackPane myStackPane;

    private Label label = new Label("Text 1");

    @FXML
    private void handleButtonAction(ActionEvent event) {
        FXMLLoader secondLoader = new FXMLLoader();

        secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));

        try {
            secondLoader.load();
        } catch (IOException e) {
        }

        FXMLSecondController secondController = secondLoader.getController();

        secondController.setFieldText(label.getText());

        Parent p = secondLoader.getRoot();
        Stage stage = new Stage();
        stage.setScene(new Scene(p));
        stage.showAndWait();
    }

    public void putLabelOnStackPane(String value) {
        label.setText(value);

        myStackPane.getChildren().add(label);
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

}

FXMLSecondController

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class FXMLSecondController implements Initializable {

    @FXML
    private Button saveText;
    @FXML
    private TextField textField;

    /**
     * Initializes the controller class.
     */


    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

    @FXML
    private void saveTextBtnPressed(ActionEvent event) {
        FXMLLoader firstLoader = new FXMLLoader();

        firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));

        try {
            firstLoader.load();
        } catch (IOException e) {
        }

        FXMLDocumentController firstController = firstLoader.getController();

        firstController.putLabelOnStackPane(textField.getText());

        Stage stage = (Stage) saveText.getScene().getWindow();
        stage.close();
    }

    public void setFieldText(String value) {
        textField.setText(value);
    }

}

FXMLDocument

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="problems.FXMLDocumentController">
    <children>
        <Button fx:id="button" layoutX="128.0" layoutY="14.0" onAction="#handleButtonAction" text="Click Me!" />
      <StackPane fx:id="myStackPane" layoutX="61.0" layoutY="45.0" prefHeight="150.0" prefWidth="200.0" />
    </children>
</AnchorPane>

FXMLSecond

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.1" fx:controller="problems.FXMLSecondController">
   <children>
      <Button fx:id="saveText" layoutX="274.0" layoutY="106.0" mnemonicParsing="false" onAction="#saveTextBtnPressed" text="Button" />
      <TextField fx:id="textField" layoutX="226.0" layoutY="175.0" />
   </children>
</AnchorPane>
2
  • Please post minimal reproducible example Commented Nov 10, 2018 at 5:12
  • I updated the question with what should be a lot more minimal and complete example of my problem. Commented Nov 10, 2018 at 17:32

1 Answer 1

1

The main issue is that by

FXMLLoader firstLoader = new FXMLLoader();
firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));

you actually construct a new FXMLLoader rather then getting a reference to the open one.
You could get a reference to the open FXMLLoader by, for example, using static members (see here) but it would be better to use a slightly different approach:

FXMLDocumentController.java

public class FXMLDocumentController implements Initializable {

    @FXML
    private Button button;
    @FXML
    private StackPane myStackPane;

    private Label label = new Label("Text 1");

    @FXML
    private void handleButtonAction(ActionEvent event) {

        FXMLLoader secondLoader = new FXMLLoader();
        secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));

        try {
            secondLoader.load();
        } catch (IOException e) {e.printStackTrace();  }

        FXMLSecondController secondController = secondLoader.getController();
        //secondController.setFieldText(label.getText());
        secondController.setTextProperty(label.textProperty());

        Parent p = secondLoader.getRoot();
        Stage stage = new Stage();
        stage.setScene(new Scene(p));
        stage.showAndWait();
        myStackPane.getChildren().add(label);
    }

    /*
    public void putLabelOnStackPane(String value) {
        label.setText(value);

        myStackPane.getChildren().add(label);
    }*/

    @Override
    public void initialize(URL url, ResourceBundle rb) { //no need to implement Initializable 
                                                         //if initialize not used 
    }    
}

FXMLSecondController.java

public class FXMLSecondController implements Initializable {

    @FXML
    private Button saveText;
    @FXML
    private TextField textField;

    private StringProperty labelStringProperty;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        textField.setEditable(true);
    }    

    @FXML
    private void saveTextBtnPressed(ActionEvent event) {

        /** By doing so you actually construct a new FXMLDocument
        FXMLLoader firstLoader = new FXMLLoader();
        firstLoader.setLocation(getClass().getResource("FXMLDocument.fxml"));

        try {
            firstLoader.load();
        } catch (IOException e) {
        }

        FXMLDocumentController firstController = firstLoader.getController();
        firstController.putLabelOnStackPane(textField.getText());
        */
        labelStringProperty.set(textField.getText());
        Stage stage = (Stage) saveText.getScene().getWindow();
        stage.close();
    }

    /*
    public void setFieldText(String value) {
        textField.setText(value);
    }*/

    public void setTextProperty(StringProperty labelStringProperty) {
        this.labelStringProperty = labelStringProperty;
        textField.setText(labelStringProperty.get());
    }
}

Also consider using Dialog for input.

EDIT To have FXMLSecondController add a label to FXMLDocoment change FXMLDocumentController to pass the needed references to FXMLSecondController:

public class FXMLDocumentController {

    @FXML
    private Button button;
    @FXML
    private StackPane myStackPane;

    private Label label = new Label("Text 1");

    @FXML
    private void handleButtonAction(ActionEvent event) {

        FXMLLoader secondLoader = new FXMLLoader();
        secondLoader.setLocation(getClass().getResource("FXMLSecond.fxml"));

        try {
            secondLoader.load();
        } catch (IOException e) {e.printStackTrace();  }

        FXMLSecondController secondController = secondLoader.getController();
        secondController.setRefrences(myStackPane.getChildren(), label);

        Parent p = secondLoader.getRoot();
        Stage stage = new Stage();
        stage.setScene(new Scene(p));
        stage.showAndWait();
    } 
}

And have FXMLSecondController use those references:

public class FXMLSecondController {

    @FXML
    private Button saveText;
    @FXML
    private TextField textField;

    private ObservableList<Node> children;
    private Label label;

    @FXML
    private void saveTextBtnPressed(ActionEvent event) {

        label.setText(textField.getText());
        children.add(label);
        Stage stage = (Stage) saveText.getScene().getWindow();
        stage.close();
    }

    public void setRefrences(ObservableList<Node> children, Label label) {      
        this.children = children;
        this.label = label;
        textField.setText(label.getText());
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you very much for the response. Your example does not add the label to the StackPane though. Which is what my problem was to begin with. I understand now that creating a new FXML Loader was creating a whole new FXML and not applying the changes to the currently open one. So, can I get a reference to the already open StackPane and add the label from the FXMLsecondcontroller? Would it be appropriate to use a static reference to the StackPane?
The "problem was to begin with" was not setting a label, but getting the right reference. I am glad my answer clarified it. You can get a static reference but it would be better to path a reference of the stackpane children by secondController.setChidren(myStackPane.getChildren()); instead ofsecondController.setTextProperty(label.textProperty()); . If needed I can add this option to the answer later.
Sorry, you are correct. My problem was getting the correct reference. I am still a little confused by "path a reference of the stackpane children..." So if you could add/update when you get a chance that would be great. Maybe it will make more sense when I see your code. I just am lost on how to reference the existing StackPane without creating a new controller. I was looking at This but I'm not sure this is correct either, and I haven't had a chance to try it with my code yet.
Updated my answer. Hope it helps.
I'm starting to follow what you're doing here... However, I'm getting a NullPointerException on this secondController.setRefrences(myStackPane.getChildren(), label); line. I'm assuming it's because the StackPane is empty, and has no children? EDIT: But, I added children and still get the nullPointer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.