Javafx:如何定位嵌套视图中的对象?
Javafx: How do you target objects in nested views?
我知道每次加载嵌套的 fxml 和控制器时,我都可以使用该控制器来操作嵌套的 fxml。例如,我可以将每隔一行设为紫色,但我不明白的是,在加载所有内容后,我如何才能针对特定的对象进行操作。
这是我能做的最简单的最小可复制示例,从这里减少的任何内容都不符合嵌套 fxml 和子项的标准。我在这里要做的是获取第一个分数,文本为“Score0”,并在按下 10 按钮时将其更改为“10”。我有一种感觉,我很接近,分数框应该是分数[0]。应该也嵌套在row[0],但是我好像无法获取scoreEntry方法来找到框来改变它。
Main.java:
public class Main extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("view1.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
view1.fxml:
<AnchorPane prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nested.Ctrl1">
<children>
<VBox fx:id="rowHolder" prefHeight="260.0" prefWidth="400.0" />
<Button mnemonicParsing="false" onAction="#scoreEntry" prefHeight="40.0" prefWidth="40.0" text="10" AnchorPane.leftAnchor="70.0" AnchorPane.topAnchor="260.0" />
<Button mnemonicParsing="false" onAction="#scoreEntry" prefHeight="40.0" prefWidth="40.0" text="0" AnchorPane.topAnchor="260.0" />
</children>
</AnchorPane>
Ctrl1.java:
public class Ctrl1 {
@FXML
private VBox rowHolder;
@FXML
void initialize() {
addRows();
}
public void addRows() {
int rounds = 2;
HBox row[];
row = new HBox[rounds];
String ctrlArray[];
ctrlArray = new String[rounds];
for (int i = 0; i < row.length; i++) {
row[i] = new HBox();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/nested/view2.fxml"));
row[i] = loader.load();
rowHolder.getChildren().add(row[i]);
Ctrl2 ctrl2 = loader.getController();
ctrlArray[i] = String.valueOf(ctrl2);
ctrl2.setRoundNum(String.valueOf(i));
System.out.println(row[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = 0; i < ctrlArray.length; i++) {
System.out.println("Controller: " + ctrlArray[i]);
}
}
private BigDecimal scoreInput;
private boolean numberInput;
@FXML
public void scoreEntry(ActionEvent event) {
Button button = (Button) event.getSource();
String buttonText = button.getText();
if (buttonText.matches("[0-10\.]")) {
if (!numberInput) {
numberInput = true;
//TODO: find Label for input text
//I think it should be something like "row[0].getChildren().score[0].clear();"
}
//And then I would append it with something like "score[0].appendText(buttonText);"
return;
}
}
}
view2.fxml
<HBox prefHeight="30.0" prefWidth="400.0" style="-fx-background-color: #77e77e;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nested.Ctrl2">
<children>
<Label fx:id="rowNum" text="Row Number" />
<HBox fx:id="scoresHolder" prefHeight="100.0" prefWidth="200.0" />
<Label fx:id="subTotal" text="Sub Total" />
<Label fx:id="total" text="Total" />
</children>
</HBox>
Ctrl2.java
public class Ctrl2 {
@FXML
private Label rowNum;
@FXML
private Label subTotal;
@FXML
private HBox scoresHolder;
@FXML
private Label total;
public void setRoundNum(String strRnd) {
rowNum.setText(strRnd);
}
public void setSubTotal(String strRnd) {
subTotal.setText(strRnd);
}
public void setTotal(String strRnd) {
total.setText(strRnd);
}
@FXML
void initialize() {
int plays = 1;
Label score[];
score = new Label[plays];
for (int i = 0; i < score.length; i++) {
score[i] = new Label("Score" + i);
scoresHolder.getChildren().add(score[i]);
System.out.println(score[i]);
}
}
}
我采纳了@James_D的建议,将我的控制器和单元封装在数组中。
//This is the array for the controllers. It's outside the method to be accessed by other methods.
public static Ctrl2[] ctrlArray = new Ctrl2[2];
public void addRows() {
int rounds = 2;
HBox row = null;
for (int i = 0; i < rounds; i++) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/nested/view2.fxml"));
row = loader.load();
rowHolder.getChildren().add(row);
ctrlArray[i] = loader.getController();
ctrlArray[i].setRoundNum(String.valueOf(i));
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = 0; i < ctrlArray.length; i++) {
System.out.println("Controller: " + ctrlArray[i]);
}
}
我遇到的问题是范围。如果我在方法之外创建数组持有者,我可以从其他方法访问它。
private Label[] score;
public void addScores() {
int plays = 2;
//Moved array holder from here to outside
score = new Label[plays];
for (int i = 0; i < score.length; i++) {
score[i] = new Label("Score" + i);
scoresHolder.getChildren().add(score[i]);
System.out.println(score[i]);
}
}
我知道每次加载嵌套的 fxml 和控制器时,我都可以使用该控制器来操作嵌套的 fxml。例如,我可以将每隔一行设为紫色,但我不明白的是,在加载所有内容后,我如何才能针对特定的对象进行操作。
这是我能做的最简单的最小可复制示例,从这里减少的任何内容都不符合嵌套 fxml 和子项的标准。我在这里要做的是获取第一个分数,文本为“Score0”,并在按下 10 按钮时将其更改为“10”。我有一种感觉,我很接近,分数框应该是分数[0]。应该也嵌套在row[0],但是我好像无法获取scoreEntry方法来找到框来改变它。
Main.java:
public class Main extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("view1.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
view1.fxml:
<AnchorPane prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nested.Ctrl1">
<children>
<VBox fx:id="rowHolder" prefHeight="260.0" prefWidth="400.0" />
<Button mnemonicParsing="false" onAction="#scoreEntry" prefHeight="40.0" prefWidth="40.0" text="10" AnchorPane.leftAnchor="70.0" AnchorPane.topAnchor="260.0" />
<Button mnemonicParsing="false" onAction="#scoreEntry" prefHeight="40.0" prefWidth="40.0" text="0" AnchorPane.topAnchor="260.0" />
</children>
</AnchorPane>
Ctrl1.java:
public class Ctrl1 {
@FXML
private VBox rowHolder;
@FXML
void initialize() {
addRows();
}
public void addRows() {
int rounds = 2;
HBox row[];
row = new HBox[rounds];
String ctrlArray[];
ctrlArray = new String[rounds];
for (int i = 0; i < row.length; i++) {
row[i] = new HBox();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/nested/view2.fxml"));
row[i] = loader.load();
rowHolder.getChildren().add(row[i]);
Ctrl2 ctrl2 = loader.getController();
ctrlArray[i] = String.valueOf(ctrl2);
ctrl2.setRoundNum(String.valueOf(i));
System.out.println(row[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = 0; i < ctrlArray.length; i++) {
System.out.println("Controller: " + ctrlArray[i]);
}
}
private BigDecimal scoreInput;
private boolean numberInput;
@FXML
public void scoreEntry(ActionEvent event) {
Button button = (Button) event.getSource();
String buttonText = button.getText();
if (buttonText.matches("[0-10\.]")) {
if (!numberInput) {
numberInput = true;
//TODO: find Label for input text
//I think it should be something like "row[0].getChildren().score[0].clear();"
}
//And then I would append it with something like "score[0].appendText(buttonText);"
return;
}
}
}
view2.fxml
<HBox prefHeight="30.0" prefWidth="400.0" style="-fx-background-color: #77e77e;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nested.Ctrl2">
<children>
<Label fx:id="rowNum" text="Row Number" />
<HBox fx:id="scoresHolder" prefHeight="100.0" prefWidth="200.0" />
<Label fx:id="subTotal" text="Sub Total" />
<Label fx:id="total" text="Total" />
</children>
</HBox>
Ctrl2.java
public class Ctrl2 {
@FXML
private Label rowNum;
@FXML
private Label subTotal;
@FXML
private HBox scoresHolder;
@FXML
private Label total;
public void setRoundNum(String strRnd) {
rowNum.setText(strRnd);
}
public void setSubTotal(String strRnd) {
subTotal.setText(strRnd);
}
public void setTotal(String strRnd) {
total.setText(strRnd);
}
@FXML
void initialize() {
int plays = 1;
Label score[];
score = new Label[plays];
for (int i = 0; i < score.length; i++) {
score[i] = new Label("Score" + i);
scoresHolder.getChildren().add(score[i]);
System.out.println(score[i]);
}
}
}
我采纳了@James_D的建议,将我的控制器和单元封装在数组中。
//This is the array for the controllers. It's outside the method to be accessed by other methods.
public static Ctrl2[] ctrlArray = new Ctrl2[2];
public void addRows() {
int rounds = 2;
HBox row = null;
for (int i = 0; i < rounds; i++) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/nested/view2.fxml"));
row = loader.load();
rowHolder.getChildren().add(row);
ctrlArray[i] = loader.getController();
ctrlArray[i].setRoundNum(String.valueOf(i));
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = 0; i < ctrlArray.length; i++) {
System.out.println("Controller: " + ctrlArray[i]);
}
}
我遇到的问题是范围。如果我在方法之外创建数组持有者,我可以从其他方法访问它。
private Label[] score;
public void addScores() {
int plays = 2;
//Moved array holder from here to outside
score = new Label[plays];
for (int i = 0; i < score.length; i++) {
score[i] = new Label("Score" + i);
scoresHolder.getChildren().add(score[i]);
System.out.println(score[i]);
}
}