getText 方法返回 null 即使用户输入了值?



首先,我有这个主要的FXML文件:

<?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>

我有它的控制器类:

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

最后,我有另一个控制器类 FirstFitController,它的初始化方法集如下:

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

基本上,用户从第一个窗口的下拉菜单中选择 First-Fit(我在最顶部发布了 FXML 文件),并在每个字段中输入值(特别是对于此问题,请注意"ofSizeField")。然后打开另一个窗口,它应该将用户在"ofSizeField"中输入的值(使用 getBinSize 方法)打印到控制台 - 但每次它都返回为 null,即使我在其中输入了一些内容。

我知道如果我在getBinSize方法中没有if语句来检查它是否等于null,我会得到NullPointerException错误,但我不明白我做错了什么,因为在单击"构建窗口"按钮并且程序执行"onBuildClicked"方法后,变量"binSize"设置如下: binSize = ofSizeField.getText();

然后调用返回 null 的方法 getBinSize。

如果有人能帮助我解决这个问题并告诉我我做错了什么,我将不胜感激。 提前致谢

编辑-

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

但首先,FXMLLoader 的加载方法似乎是一种静态方法 - 那么为什么需要创建一个对象呢? 其次,我不太明白如何使用"ffc"(FirstFitController的实例)?

谢谢

我这边的一点猜测:

从用户输入值的FXMLDocumentController实例开始。 然后FirstFitController被调用为另一个窗口(这是正确的吗?它在其initialize方法中创建FXMLDocumentController的实例。现在,该实例与用户输入值的第一个实例不同。因此binSizenull.

解决方案是将第一个FXMLDocumentController的引用传递给它可以从中读取值的FirstFitController(尤其是不要创建新实例)。(或者创建一个单独的类来保存实际值并将其传递。

编辑:

当您为 FirstFitController 加载 FXML 时,请执行以下操作:

FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource(fxmlName + ".fxml"));
FirstFitController ffc = (FirstFitController) fxmlLoader.getController();

然后,您可以访问FirstFitController的实际实例并根据需要设置任何成员。(需要创建FxmlLoader实例才能检索控制器。

最新更新