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>
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());
}
}