首页 文章

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

提问于
浏览
0

在使用FXMLLoader动态创建后,我很难将FXML Text组件更新 . 这个假设简单的程序要求用户输入掷骰数,根据此输入创建新骰子,使用随机数生成器滚动它们,对这些值求和,并提供按钮以重新滚动任何骰子想 . 每个模具都添加到主窗口(使用FXMLoader和自定义模具组件),显示其索引,滚动值以及如果要重新滚动特定模具而推动的按钮 . 模具的值存在并且更新很好 . 重新滚动按钮效果很好 . 但是,出于某种原因,每个骰子的索引都没有显示在窗口中 - 甚至最初都没有 . 有问题的Text组件(不显示任何值的组件)在自定义FXML文档中标识为fx:id = "number",在自定义控制器中标识为@FXML私有文本编号 .

我是'm assuming the issue has to do with the Text component'的getter和setter,我很幸运,Text组件名为value . 但是,如果是这种情况,那么正确的名字已经提到了我,因为我已经检查了许多涉及名称中的 property 的替代方案等 .

注意:我理解当按下重新滚动按钮时,不会更新骰子值的总和 . 我现在只关心正在更新的模具值 .

该程序的主要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>

主要控制器是:

public class MainWindowController implements Initializable {

@FXML
Label spinnerText;

@FXML
Spinner spinner;

@FXML
HBox buttonBox;

@FXML
Text dieNumber;

@FXML
Text sumNumber;

@FXML
int numberOfDice = 0;

@FXML
int sumOfDice = 0;

@FXML
VBox rowBox;

private List<Die> dieList = new ArrayList<>();
private List<GridPane> rowList = new ArrayList<>();

public void createDice() throws IOException{
    numberOfDice = (int)spinner.getValue();

    for (int i=0;i<numberOfDice;i++){
        Die die = new Die(i);
        die.roll(null);
        sumOfDice = sumOfDice + Integer.parseInt(die.getValue());
        dieList.add(die);
        rowBox.getChildren().add(die);
    }
    dieNumber.setText(String.valueOf(numberOfDice));
    sumNumber.setText(String.valueOf(sumOfDice));
    spinner.setVisible(false);
    spinnerText.setVisible(false);
    buttonBox.setVisible(false);
}

/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    spinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 20));
    dieNumber.setText("0");
    sumNumber.setText(String.valueOf("0"));
    spinnerText.setVisible(true);
    spinner.setVisible(true);
    buttonBox.setVisible(true);

}    
}

在上面的for循环中动态创建的die自定义组件是(问题组件是fx:id = "number"):

<fx:root type="javafx.scene.layout.GridPane" 
      xmlns:fx="http://javafx.com/fxml/1"  
      xmlns="http://javafx.com/javafx/8.0_40" >
<HBox spacing="30" alignment="center" GridPane.columnIndex="0" GridPane.rowIndex="0"  >
    <Text fx:id="number" /><!--This is the problem component-->
    <Text fx:id="value"/>
    <Button fx:id="dieButton" text="Roll Dice" onAction="#roll"  />
</HBox>
</fx:root>

它动态创建的控制器是:

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) {
}
}

1 回答

  • 0

    问题是您创建了一个新的 Text 实例,而不是配置已在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));
    }
    

相关问题