To start with, I have this main FXML file:
<?xml version="1.0" encoding="UTF-8"?>
<?import binpacking.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" prefHeight="582.0" prefWidth="556.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="binpacking.FXMLDocumentController">
<children>
<Label id="TypeLabel" fx:id="typeLabel" layoutX="186.0" layoutY="77.0" text="Type:" />
<ComboBox id="TypeOfAlgorithm" fx:id="typeOfAlgorithmCombo" layoutX="239.0" layoutY="77.0">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="First-Fit" />
<String fx:value="First-Fit Decreasing" />
<String fx:value="Full-Bin Packing" />
</FXCollections>
</items>
</ComboBox>
<Label fx:id="numbersLabel" layoutX="242.0" layoutY="148.0" prefWidth="65.0" text="Numbers:" />
<Group id="Group" layoutX="138.0" layoutY="173.0" scaleX="1.0" scaleY="1.0">
<children>
<TextField id="no1" fx:id="no1Field" layoutX="0.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.999900000002526" />
<TextField id="no2" fx:id="no2Field" layoutX="43.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.999900000002526" />
<TextField id="no3Field" fx:id="no3Field" layoutX="95.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.9998779296875" />
<TextField id="no4Field" fx:id="no4Field" layoutX="148.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.9998779296875" />
<TextField id="no5Field" fx:id="no5Field" layoutX="191.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.9998779296875" />
<TextField id="no6Field" fx:id="no6Field" layoutX="236.0" layoutY="0.0" prefHeight="21.0" prefWidth="34.9998779296875" />
</children>
</Group>
<Label id="noOfBinsLabel" fx:id="noOfBinsLabel" layoutX="224.0" layoutY="291.0" text="Number of Bins:" />
<Label id="ofSizeLabel" fx:id="ofSizeLabel" layoutX="228.0" layoutY="360.0" text="of Size:" />
<TextField id="ofSizeField" fx:id="ofSizeField" layoutX="286.0" layoutY="360.0" prefHeight="21.0" prefWidth="34.9998779296875" />
<Button fx:id="buildButton" layoutX="171.0" layoutY="507.0" mnemonicParsing="false" onAction="#onBuildClicked" text="Build Window" />
<Button fx:id="resetButton" layoutX="300.0" layoutY="508.0" mnemonicParsing="false" onAction="#onResetClicked" text="Reset" />
<Label alignment="CENTER" contentDisplay="CENTER" layoutX="136.0" layoutY="15.0" text="The Bin Packing Program" textOverrun="CENTER_ELLIPSIS">
<font>
<Font name="System Bold" size="22.0" />
</font>
</Label>
<MenuBar fx:id="MenuBar" layoutX="0.0" layoutY="0.0" useSystemMenuBar="true">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<Slider fx:id="noOfBinsSlider" layoutX="203.0" layoutY="325.0" max="6.0" min="1.0" value="6.0" />
</children>
</AnchorPane>
And I have the controller class for it:
package binpacking;
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.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.MenuBar;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class FXMLDocumentController implements Initializable {
// Declaration of strings which hold user data input
private String typeOfAlgorithmString;
private String numberOfBins;
private String binSize;
private String[] numbers = new String[6];
@FXML
private Label typeLabel;
@FXML
private ComboBox<?> typeOfAlgorithmCombo;
@FXML
private TextField no1Field;
@FXML
private TextField no2Field;
@FXML
private TextField no3Field;
@FXML
private TextField no4Field;
@FXML
private TextField no5Field;
@FXML
private TextField no6Field;
@FXML
private Label noOfBinsLabel;
@FXML
private Label ofSizeLabel;
@FXML
private TextField ofSizeField;
@FXML
private Label numbersLabel;
@FXML
private Button buildButton;
@FXML
private Button resetButton;
@FXML
private MenuBar menuBar;
@FXML
private Slider noOfBinsSlider;
@Override
public void initialize(URL url, ResourceBundle rb) {
// Menu bar preparation code to be added here
}
public void changeStage(String fxmlName) throws Exception {
// Load FXML - based on the fxmlName parameter
Parent root = FXMLLoader.load(getClass().getResource(fxmlName + ".fxml"));
// Create objects of the stage and scene
Stage stage = new Stage();
Scene scene = new Scene(root);
// Show the new stage/open new window
stage.setScene(scene);
// Detect title for the window
if (fxmlName == "FirstFit")
{
stage.setTitle("First-Fit");
} else if (fxmlName == "FirstFitDecreasing") {
stage.setTitle("First-Fit Decreasing");
} else {
stage.setTitle("Full-Bin Packing");
}
stage.show();
}
@FXML
private void onBuildClicked(ActionEvent event) {
// Get Type Of Algorithm
typeOfAlgorithmString = (String) typeOfAlgorithmCombo.getValue();
// Get Numbers Input
numbers[0] = no1Field.getText();
numbers[1] = no2Field.getText();
numbers[2] = no3Field.getText();
numbers[3] = no4Field.getText();
numbers[4] = no5Field.getText();
numbers[5] = no6Field.getText();
// Get Number Of Bins
// numberOfBins = String.valueOf(noOfBinsSlider.getValue());
// Get Bin Size
binSize = ofSizeField.getText();
// Create Objects of Each Algorithm's Class
FirstFit firstFitClass = new FirstFit();
FirstFitDecreasing firstFitDecreasingClass = new FirstFitDecreasing();
FullBin fullBinClass = new FullBin();
// Determine Type Of Algorithm To Run
switch (typeOfAlgorithmString.toLowerCase()) {
case "first-fit":
firstFitClass.runAlgorithm();
break;
case "first-fit decreasing":
firstFitDecreasingClass.runAlgorithm();
break;
case "full-bin packing":
fullBinClass.runAlgorithm();
break;
default:
System.out.println("Invalid algorithm type.");
break;
}
}
@FXML
private void onResetClicked(ActionEvent event) {
no1Field.setText(null);
no2Field.setText(null);
no3Field.setText(null);
no4Field.setText(null);
no5Field.setText(null);
no6Field.setText(null);
ofSizeField.setText(null);
}
public String getBinSize() {
if (binSize == null) {
binSize = "Bin size field is null.";
}
return binSize;
}
}
And at last, I have another controller class FirstFitController, which has the initialise method set like this:
@Override
public void initialize(URL url, ResourceBundle rb) {
// Create object of main controller so we can access the fields
FXMLDocumentController mainController = new FXMLDocumentController();
// Get and print value of bin size label
System.out.println(mainController.getBinSize());
// binSizeBottomLabel.setText("Bin size: " + mainController.getBinSize());
}
Basically, the user selects First-Fit from the drop down menu in the first window (which I posted the FXML file for at the very top) and also enters values in every field (specifically for this problem please note "ofSizeField"). Then another window opens and it is supposed to print to the console the value of what the user has entered in the "ofSizeField" (using the getBinSize method) - but every time it returns as null even though I enter something in it.
I understand I would get the NullPointerException error if I didn't have the if statement in the getBinSize method to check whether or not it is equal to null, but I don't understand what I have done wrong because after the "Build Window" button is clicked and the program executes the "onBuildClicked" method, the variable "binSize" is set like this:
binSize = ofSizeField.getText();
and then the method getBinSize is called which returns null.
If anyone could please help me with this and tell me what I am doing wrong, I would appreciate it a lot.
Thanks in advance
EDIT -
So my changeStage(String fxmlName) contains these lines of code:
public void changeStage(String fxmlName) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource(fxmlName + ".fxml"));
FirstFitController ffc = (FirstFitController) fxmlLoader.getController();
// Create objects of the stage and scene
Stage stage = new Stage();
Scene scene = new Scene(p);
// Show the new stage/open new window
stage.setScene(scene);
// Detect title for the window
if (fxmlName == "FirstFit")
{
stage.setTitle("First-Fit");
} else if (fxmlName == "FirstFitDecreasing") {
stage.setTitle("First-Fit Decreasing");
} else {
stage.setTitle("Full-Bin Packing");
}
stage.show();
}
But firstly, it seems that the load method of FXMLLoader is a static method - so why is it necessary to create an object?
And secondly, I didn't quite understand how I would use "ffc" (the instance of FirstFitController)?
Thanks