在多个 FXML 之间交互
Interact between several FXMLs
我正在尝试使用 javaFX 和 FXML 文件编写我的第一个应用程序,但我无法访问 FXML 的变量。
我可以从第一个场景(第一个 FXML)启动程序。有一个我可以与之交互的按钮,第一个场景隐藏,第二个场景出现。在那个场景中,用户必须在文本字段中插入一个值。通过在另一个按钮上确认此输入,我可以将其保存到变量中。
单击此按钮可隐藏第二个场景并再次打开第一个场景。现在我想将第一个场景中的标签值设置为我保存用户输入的变量值。但这会引发错误消息。
似乎此标签值不可访问,即使此标签是当前加载的 FXML 的一部分,但我能够获得第二个 FXML(用户交互字段)的标签值,该值不再可见。
谁能帮帮我,如何让第一个FXML的这个Label可读可改?
我的代码很长,但我懒得给你最重要的部分:
@FXML
private Label RollsMax;
@FXML
private TextField roll_input;
@FXML
private String amountRolls;
... // several more declarations
@FXML
void btn_confirmInput_onClick(ActionEvent event){ //btn_confirmInput is part of scene2.fxml
event.consume();
amountRolls=roll_input.getText();
System.out.println(amountRolls); // here I get the result of the user's input
try{
root=FXMLLoader.load(getClass().getResource("project/scene1.fxml"));
stage=(Stage)((Node)event.getSource()).getScene().getWindow();
scene=new Scene(root);
stage.setScene(scene);
stage.show();
} //end try
catch (IOException e){
e.printStackTrace();
} //end catch
RollsMax.setText(amountRolls); // THIS LINE IS NOT WORKING AS RollsMax SEEMS NOT AVAILABLE, EVEN IF IT IS PART OF SCENE1.fxml
} // end btn_confirmInput_onClick()
有什么想法吗?我得到的错误是 'java.lang.RuntimeException: java.lang.reflect.InvocationtargetException' 以及 'java.lang.NullPointerException'.
非常感谢!
编码器
为每个 FXML 使用控制器 class。然后你应该能够使用 public 方法在它们之间进行交互。
特别是当你只隐藏第一个场景时,你应该能够从一个场景写到另一个场景。
或者:在启动第二个场景时创建一个参数,将第一个场景的实例引入其中。比您应该能够在第一个场景实例上使用所需的方法。
喜欢
代码场景一
@FXML
private void startSceneTwoButton(){
new SceneTwo(this);
}
代码场景二
FirstScene scene;
public SecondScene(FirstScene scene){
this.scene = scene;
//some code
}
@FXML
private void button(){
scene.enterValue(value);
}
为了在场景之间共享数据,我们将引入一个 Model
class 来保存共享信息:
public class Model {
private SimpleStringProperty valueProperty = new SimpleStringProperty("N/A");
public SimpleStringProperty getValueProperty() {
return valueProperty;
}
}
以及两个场景的控制器(实际上是两个场景的两个根的控制器)要实现的接口。
接口增加了向controller中注入aModel
的功能:
public interface Controller {
void setModel(Model model);
}
sceneOne.fxml
带有切换场景的按钮和显示用户输入的标签:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneOneController">
<children>
<Label layoutX="159.0" layoutY="40.0" text="Scene 1">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Get Input" />
<Label fx:id="inputValue" layoutX="187.0" layoutY="142.0" text="Label" />
</children>
</AnchorPane>
及其实现Controller
接口的控制器:
public class SceneOneController implements Controller {
@FXML Label inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneTwo.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneTwo controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
inputValue.textProperty().bind(model.valueProperty);
}
}
}
sceneTwo.fxml
带有切换场景的按钮和用于用户输入的 TextField:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="main" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneTwoController">
<children>
<Label layoutX="150.0" layoutY="41.0" text="Scene 2">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Update" />
<TextField fx:id="inputValue" layoutX="121.0" layoutY="138.0" prefHeight="25.0" prefWidth="162.0" />
</children>
</AnchorPane>
及其控制器:
public class SceneTwoController implements Controller {
@FXML TextField inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneOne controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
model.valueProperty.bind(inputValue.textProperty());
}
}
}
最后是用于测试的应用程序:
public class SwitchSceneMVC extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Model model = new Model();
Controller controller = loader.getController();
controller.setModel(model);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}
我正在尝试使用 javaFX 和 FXML 文件编写我的第一个应用程序,但我无法访问 FXML 的变量。
我可以从第一个场景(第一个 FXML)启动程序。有一个我可以与之交互的按钮,第一个场景隐藏,第二个场景出现。在那个场景中,用户必须在文本字段中插入一个值。通过在另一个按钮上确认此输入,我可以将其保存到变量中。 单击此按钮可隐藏第二个场景并再次打开第一个场景。现在我想将第一个场景中的标签值设置为我保存用户输入的变量值。但这会引发错误消息。 似乎此标签值不可访问,即使此标签是当前加载的 FXML 的一部分,但我能够获得第二个 FXML(用户交互字段)的标签值,该值不再可见。
谁能帮帮我,如何让第一个FXML的这个Label可读可改? 我的代码很长,但我懒得给你最重要的部分:
@FXML
private Label RollsMax;
@FXML
private TextField roll_input;
@FXML
private String amountRolls;
... // several more declarations
@FXML
void btn_confirmInput_onClick(ActionEvent event){ //btn_confirmInput is part of scene2.fxml
event.consume();
amountRolls=roll_input.getText();
System.out.println(amountRolls); // here I get the result of the user's input
try{
root=FXMLLoader.load(getClass().getResource("project/scene1.fxml"));
stage=(Stage)((Node)event.getSource()).getScene().getWindow();
scene=new Scene(root);
stage.setScene(scene);
stage.show();
} //end try
catch (IOException e){
e.printStackTrace();
} //end catch
RollsMax.setText(amountRolls); // THIS LINE IS NOT WORKING AS RollsMax SEEMS NOT AVAILABLE, EVEN IF IT IS PART OF SCENE1.fxml
} // end btn_confirmInput_onClick()
有什么想法吗?我得到的错误是 'java.lang.RuntimeException: java.lang.reflect.InvocationtargetException' 以及 'java.lang.NullPointerException'.
非常感谢! 编码器
为每个 FXML 使用控制器 class。然后你应该能够使用 public 方法在它们之间进行交互。
特别是当你只隐藏第一个场景时,你应该能够从一个场景写到另一个场景。
或者:在启动第二个场景时创建一个参数,将第一个场景的实例引入其中。比您应该能够在第一个场景实例上使用所需的方法。
喜欢
代码场景一
@FXML
private void startSceneTwoButton(){
new SceneTwo(this);
}
代码场景二
FirstScene scene;
public SecondScene(FirstScene scene){
this.scene = scene;
//some code
}
@FXML
private void button(){
scene.enterValue(value);
}
为了在场景之间共享数据,我们将引入一个 Model
class 来保存共享信息:
public class Model {
private SimpleStringProperty valueProperty = new SimpleStringProperty("N/A");
public SimpleStringProperty getValueProperty() {
return valueProperty;
}
}
以及两个场景的控制器(实际上是两个场景的两个根的控制器)要实现的接口。
接口增加了向controller中注入aModel
的功能:
public interface Controller {
void setModel(Model model);
}
sceneOne.fxml
带有切换场景的按钮和显示用户输入的标签:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneOneController">
<children>
<Label layoutX="159.0" layoutY="40.0" text="Scene 1">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Get Input" />
<Label fx:id="inputValue" layoutX="187.0" layoutY="142.0" text="Label" />
</children>
</AnchorPane>
及其实现Controller
接口的控制器:
public class SceneOneController implements Controller {
@FXML Label inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneTwo.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneTwo controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
inputValue.textProperty().bind(model.valueProperty);
}
}
}
sceneTwo.fxml
带有切换场景的按钮和用于用户输入的 TextField:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="main" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneTwoController">
<children>
<Label layoutX="150.0" layoutY="41.0" text="Scene 2">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Update" />
<TextField fx:id="inputValue" layoutX="121.0" layoutY="138.0" prefHeight="25.0" prefWidth="162.0" />
</children>
</AnchorPane>
及其控制器:
public class SceneTwoController implements Controller {
@FXML TextField inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneOne controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
model.valueProperty.bind(inputValue.textProperty());
}
}
}
最后是用于测试的应用程序:
public class SwitchSceneMVC extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Model model = new Model();
Controller controller = loader.getController();
controller.setModel(model);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}