JavaFX FXML文本组件控制器未更新

JavaFX FXML文本组件控制器未更新,javafx,dynamic,custom-controls,fxml,fxmlloader,Javafx,Dynamic,Custom Controls,Fxml,Fxmlloader,在使用FXMLLoader动态创建FXML文本组件之后,我很难让它更新。这个假定很简单的程序要求用户输入要掷骰子的数量,根据此输入创建新骰子,使用随机数生成器掷骰子,对这些值求和,并提供一个按钮,如果用户需要,可以重新掷骰子。每个模具都使用FXMLoader和一个自定义模具组件添加到主窗口,该组件显示其索引、滚动值,如果要重新滚动特定模具,还可以按下一个按钮。模具的值显示和更新非常好。重新滚动按钮工作得很好。然而,由于某些原因,每个模具的索引不会显示在窗口中,甚至最初也不会显示。所讨论的文本组件

在使用FXMLLoader动态创建FXML文本组件之后,我很难让它更新。这个假定很简单的程序要求用户输入要掷骰子的数量,根据此输入创建新骰子,使用随机数生成器掷骰子,对这些值求和,并提供一个按钮,如果用户需要,可以重新掷骰子。每个模具都使用FXMLoader和一个自定义模具组件添加到主窗口,该组件显示其索引、滚动值,如果要重新滚动特定模具,还可以按下一个按钮。模具的值显示和更新非常好。重新滚动按钮工作得很好。然而,由于某些原因,每个模具的索引不会显示在窗口中,甚至最初也不会显示。所讨论的文本组件(即不显示任何值的组件)在自定义FXML文档中标识为fx:id=number,在自定义控制器中标识为@FXML private Text number

我假设这个问题与文本组件的getter和setter有关,幸运的是,名为value的文本组件可以工作。然而,如果是这样的话,专有名称已经暗示了我,因为我已经检查了许多涉及名称中的属性的备选方案,等等

注:我知道当按下重新滚动按钮时,模具值的总和不会更新。我现在只关心正在更新的模具值

该程序的主FXML窗口为:

<GridPane   fx:id="mainPane" 
        styleClass="mainFxmlClass" 
        xmlns:fx="http://javafx.com/fxml/1" 
        fx:controller="org.lgdor.dieSim.MainWindowController" 
        xmlns="http://javafx.com/javafx/8.0_40"
        prefHeight="800.0" 
        prefWidth="800.0" 
        hgap="10" 
        vgap="10" >
<stylesheets>
    <URL value="@mainwindow.css"/>
</stylesheets>
<padding>
    <Insets top="25" right="25" bottom="10" left="25"/>
</padding>
<Text fx:id="welcomeText" text="Welcome to DieSim" 
      GridPane.columnIndex="0" 
      GridPane.rowIndex="0"
      GridPane.columnSpan="5"/>
<Label fx:id="spinnerText"
       text="Please input the number of dice you want to roll:"
       GridPane.columnIndex="0" 
       GridPane.rowIndex="1"
       GridPane.columnSpan="2"/>
<Spinner fx:id="spinner" editable="true" 
         GridPane.columnIndex="3" 
         GridPane.rowIndex="1" />
<HBox fx:id="buttonBox"
      spacing="10" 
      alignment="center" 
      GridPane.columnIndex="5" 
      GridPane.rowIndex="1">
    <Button text="Roll Dice" onAction="#createDice"/>

</HBox>
<Label fx:id="dieNumberText" text="The number of dice is: "
      GridPane.columnIndex="0" 
      GridPane.rowIndex="2"
      GridPane.columnSpan="2"/>
<Text fx:id="dieNumber" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Label fx:id="dieSumText" text="The sum of the dice is: "
      GridPane.columnIndex="0" 
      GridPane.rowIndex="3"
      GridPane.columnSpan="2"/>
<Text fx:id="sumNumber" GridPane.columnIndex="3" GridPane.rowIndex="3" />
<VBox fx:id="rowBox"
      spacing="10" 
      alignment="center" 
      GridPane.columnIndex="0" 
      GridPane.rowIndex="4"
      GridPane.columnSpan="5" >
    <Text text="This is where the list of dice goes..."/>

</VBox>

问题是您创建了一个新的文本实例,而不是配置FXML中已经创建的文本实例:

this.number = new Text(String.valueOf(i));
@FXML注释的全部目的是指示字段由FXMLLoader初始化,因此初始化@FXML注释的字段总是错误的

请注意,这些字段在调用load期间由FXMLLoader初始化,因此您需要在以任何方式配置它们之前调用load

因此,您的构造函数应该如下所示:

public Die(int i) throws IOException{
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("DieGUI.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    fxmlLoader.load();  

    // these don't seem to do anything useful?
    // this.setNumber(String.valueOf(1));
    // this.setValue(String.valueOf(1));

    this.number.setText(String.valueOf(i));
    this.value.setText(String.valueOf(i));
}

只是快速浏览了一下您的代码,我发现了两个可能的问题。首先,调用setNumberString.valueOf1一次,然后再也不为其设置其他值。其次,在构造函数中创建数字文本字段,但同时使用@FXML对其进行注释。这是因为您的Die类是一个扩展GridPane的UI组件,同时也是一个完全不同的UI组件DieGUI的控制器。这就做到了!谢谢这么简单。
public class Die extends GridPane implements Initializable {

@FXML
private Text number;//This is the problem component ...
public String getNumber() {
    return numberTextProperty().get();
}
public void setNumber(String number) {
    numberTextProperty().set(number);
}
public StringProperty numberTextProperty() {
    return number.textProperty();
}

@FXML
private Text value;
public String getValue() {
    return valueTextProperty().get();
}
public void setValue(String value) {
    valueTextProperty().set(value);
}
public StringProperty valueTextProperty() {
    return value.textProperty();
}

public Die(int i) throws IOException{
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("DieGUI.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    this.number = new Text(String.valueOf(i));
    this.setNumber(String.valueOf(1));
    this.value = new Text();
    this.setValue(String.valueOf(1));
    fxmlLoader.load();  
}

@FXML
public void roll(ActionEvent event){
    this.setValue(String.valueOf((int)(6*Math.random()+1)));
}

@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
this.number = new Text(String.valueOf(i));
public Die(int i) throws IOException{
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("DieGUI.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    fxmlLoader.load();  

    // these don't seem to do anything useful?
    // this.setNumber(String.valueOf(1));
    // this.setValue(String.valueOf(1));

    this.number.setText(String.valueOf(i));
    this.value.setText(String.valueOf(i));
}