JavaFX FXML文本组件控制器未更新
在使用FXMLLoader动态创建FXML文本组件之后,我很难让它更新。这个假定很简单的程序要求用户输入要掷骰子的数量,根据此输入创建新骰子,使用随机数生成器掷骰子,对这些值求和,并提供一个按钮,如果用户需要,可以重新掷骰子。每个模具都使用FXMLoader和一个自定义模具组件添加到主窗口,该组件显示其索引、滚动值,如果要重新滚动特定模具,还可以按下一个按钮。模具的值显示和更新非常好。重新滚动按钮工作得很好。然而,由于某些原因,每个模具的索引不会显示在窗口中,甚至最初也不会显示。所讨论的文本组件(即不显示任何值的组件)在自定义FXML文档中标识为fx:id=number,在自定义控制器中标识为@FXML private Text number 我假设这个问题与文本组件的getter和setter有关,幸运的是,名为value的文本组件可以工作。然而,如果是这样的话,专有名称已经暗示了我,因为我已经检查了许多涉及名称中的属性的备选方案,等等 注:我知道当按下重新滚动按钮时,模具值的总和不会更新。我现在只关心正在更新的模具值 该程序的主FXML窗口为:JavaFX FXML文本组件控制器未更新,javafx,dynamic,custom-controls,fxml,fxmlloader,Javafx,Dynamic,Custom Controls,Fxml,Fxmlloader,在使用FXMLLoader动态创建FXML文本组件之后,我很难让它更新。这个假定很简单的程序要求用户输入要掷骰子的数量,根据此输入创建新骰子,使用随机数生成器掷骰子,对这些值求和,并提供一个按钮,如果用户需要,可以重新掷骰子。每个模具都使用FXMLoader和一个自定义模具组件添加到主窗口,该组件显示其索引、滚动值,如果要重新滚动特定模具,还可以按下一个按钮。模具的值显示和更新非常好。重新滚动按钮工作得很好。然而,由于某些原因,每个模具的索引不会显示在窗口中,甚至最初也不会显示。所讨论的文本组件
<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));
}