Javafx 将参数和值从一个控制器传递到另一个控制器 [英] Javafx pass parameter and values from one controller to another
问题描述
我是 JavaFx 的新手,因此我找不到解决我问题的解决方案
I am new to JavaFx and hence I cannot find a solution to solve my problem
假设我有以下应用程序结构:
Suppose I have following application structure :
- views
- first.fxml -> this has a button called btnSend and a textfield called txtEnter
- second.fxml -> this has a textarea called txtView
- Controller
- FirstController -> controller for First
- SecondController -> controller for second
- Modal
- AppModal -> here I have a getter and a setter method ,
as getText() and setText(String text)
- App
- Main.java -> This one used FXMLLoader to load first.fxml and second.fxml together.
在从 FirstController 传递的 SecondController 中显示文本的最佳/最佳方式是什么.我的意思是,我在 txtEnter
中输入一个文本,然后按下按钮 btnSend
,按下按钮后我希望文本显示在 txtView
中正在使用另一个控制器.我已经阅读了很多关于 observers pattern
和 JavaFX properties
可以用来解决这个问题,但不幸的是我无法实现一个有效的解决方案.
What is the optimal/best way to display the text in SecondController passing it from FirstController. I mean, I enter a text in txtEnter
and press the button btnSend
and after pressing the button I want the text to be displayed in txtView
which is using another controller.
I have read a lot about the observers pattern
and JavaFX properties
can be used to solve this, but unfortunately I am unable to implement a working solution.
如果您的专家能在这方面帮助我,我将不胜感激.我知道它不正确,但任何人都可以为上述项目结构提供一个可行的解决方案.
I would be humbly thankful if you experts can help me in this. I know its not correct but can anyone please give me a working solution for the above project structure.
提前致谢.
推荐答案
在模型中使用可观察的StringProperty
:
Use an observable StringProperty
in the model:
public class AppModel {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text ;
}
public final String getText() {
return textProperty().get();
}
public final void setText(String text) {
textProperty().set(text);
}
}
让你的控制器可以访问模型:
Make your controllers have access to the model:
public class FirstController {
private final AppModel model ;
@FXML
private TextField textEnter ;
public FirstController(AppModel model) {
this.model = model ;
}
// action event handler for button:
@FXML
private void sendText() {
model.setText(textEnter.getText());
}
}
和
public class SecondController {
private final AppModel model ;
@FXML
private TextArea txtView ;
public SecondController(AppModel model) {
this.model = model ;
}
public void initialize() {
// update text area if text in model changes:
model.textProperty().addListener((obs, oldText, newText) ->
txtView.setText(newText));
}
}
现在稍微有点棘手的部分是控制器没有无参数构造函数,这意味着 FXMLLoader
创建它们的默认机制将不起作用.最简单的方法是手动设置它们.从 FXML 文件中删除
属性,然后在您的 Main
类中执行
The slightly tricky part now is that the controllers don't have a no-arg constructor, which means the default mechanism for the FXMLLoader
to create them won't work. The easiest way is to set them manually. Remove both the <fx:controller>
attributes from the FXML files, and then in your Main
class do
AppModel model = new AppModel();
FXMLLoader firstLoader = new FXMLLoader(getClass().getResource("first.fxml"));
firstLoader.setController(new FirstController(model));
Parent firstUI = firstLoader.load();
FXMLLoader secondLoader = new FXMLLoader(getClass().getResource("second.fxml"));
secondLoader.setController(new SecondController(model));
Parent secondUI = secondLoader.load();
如果您希望在 FXML 文件中保留 <fx:controller>
属性,您可以使用 controllerFactory
代替,它实质上指示 FXMLLoader
关于如何创建控制器:
If you prefer to keep the <fx:controller>
attributes in the FXML files, you can use a controllerFactory
instead, which essentially instructs the FXMLLoader
as to how to create a controller:
AppModel model = new AppModel();
Callback<Class<?>, Object> controllerFactory = type -> {
if (type == FirstController.class) {
return new FirstController(model);
} else if (type == SecondController.class) {
return new SecondController(model);
} else {
try {
return type.newInstance() ; // default behavior - invoke no-arg construtor
} catch (Exception exc) {
System.err.println("Could not create controller for "+type.getName());
throw new RuntimeException(exc);
}
}
};
FXMLLoader firstLoader = new FXMLLoader(getClass().getResource("first.fxml"));
firstLoader.setControllerFactory(controllerFactory);
Parent firstUI = firstLoader.load();
FXMLLoader secondLoader = new FXMLLoader(getClass().getResource("second.fxml"));
secondLoader.setControllerFactory(controllerFactory);
Parent secondUI = secondLoader.load();
您可以通过使用(更多)反射使控制器工厂更加灵活;基本上你可以实现逻辑如果控制器类型有一个采用 AppModel
的构造函数,则调用该构造函数,否则调用无参数构造函数".
You can make the controller factory even more flexible by using (more) reflection; basically you can implement the logic "if the controller type has a constructor taking an AppModel
, call that constructor, otherwise call the no-arg constructor".
如果您正在创建一个需要执行大量此类操作的大型应用程序,那么您可以考虑使用 afterburner.fx,这是一个框架,它本质上允许您使用注释将模型注入到控制器中.
If you are creating a large application which needs to do a lot of this, then you might consider using afterburner.fx, which is a framework that essentially allows you to inject the model into the controllers using annotations.
这篇关于Javafx 将参数和值从一个控制器传递到另一个控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!