我是Java FX的新手,对控制器,FXML文件及其交互有一些基本的了解。
我正在使用Scenebuilder并尝试了一些简单的方法。 我有一个只有一个AnchorPane的FXML文件,它与Controller类链接。应该是我的主要课程,与其他FXML控制器一起玩。
我有一个“Knopf”FXML,其中包含一个带有控制器“KnopfController”的按钮 我有一个“Feld”FXML,其中包含一个Textfield,它的控制器是“FeldController”。
“Knopf.FXML”和“Feld.FXML”都包含在Anchor Pane中。
我的代码如下:
package sample;
import javafx.fxml.FXML;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
public class Controller {
@FXML
private AnchorPane Main;
@FXML
private FeldController feldController;
@FXML
private KnopfController knopfController;
public void textChange(MouseEvent event){
//Hier Comes the Code
}
现在我的问题是:
如何在我的按钮(如果已按下)和我的TextField(按下按钮时应该说“Hello”)之间进行交互?
按钮(Knopf.FXML中的fx:id =“Knopf”)和Feld.FXML中的TextField(fx:id =“Feld”)都可以用于我。
我如何存档?
我知道我只能在Controller中使用它们,但我想练习控制器和FXML文件之间的交互。
答案 0 :(得分:0)
一种简单的方法就是在每个控制器中定义所需的方法,并从事件处理程序中调用它们。在这种情况下,您的KnopfController
需要在主控制器中调用textChange()
方法(因此需要引用Controller
),然后textChange()
将调用FeldController
中的方法。
所以你会做这样的事情:
public class FeldController {
@FXML
private TextField textField ;
public void updateText(String text) {
textField.setText(text);
}
}
KnopfController
需要引用"主控制器",所以它需要
public class KnopfController {
private Controller mainController ;
public void setMainController(Controller mainController) {
this.mainController = mainController ;
}
// button handler:
@FXML
private void handleButtonClick(ActionEvent event) {
mainController.textChange("Hello");
}
}
现在你的主控制器将它们连接在一起:
public class Controller {
@FXML
private AnchorPane Main;
@FXML
private FeldController feldController;
@FXML
private KnopfController knopfController;
public void initialize() {
knopfController.setMainController(this);
}
public void textChange(String newText){
feldController.updateText(newText);
}
}
虽然这有效,但这里的设计问题是你已经将控制器紧密耦合(例如你的KnopfController
取决于Controller
类,这在某种程度上违背了将其分解为首先是一个单独的FXML控制器对。更好的方法是在控制器之间共享数据模型,并更新/观察模型。
E.g:
public class Model {
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);
}
}
现在基本的想法是
public class KnopfController {
private Model model ;
@FXML
private void handleButton() {
model.setText("Hello");
}
}
和
public class FeldController {
@FXML
private TextField textField ;
private Model model ;
// ...
textField.textProperty().bindBidirectional(model.textProperty());
// ...
}
当然,这两个控制器都需要引用相同的模型实例才能使其工作,因此您需要注入"注入"这进入控制器。您只需创建setModel()
方法并调用它们即可完成此操作:
public class KnopfController {
private Model model ;
public void setModel(Model model) {
this.model = model ;
}
@FXML
private void handleButton() {
model.setText("Hello");
}
}
和FeldController
您可以在设置模型时执行绑定:
public class FeldController {
@FXML
private TextField textField ;
private Model model ;
public void setModel(Model model) {
this.model = model ;
textField.textProperty().bindBidirectional(model.textProperty());
}
}
然后你的主控制器就缩小为:
public class Controller {
private Model model ;
@FXML
private FeldController feldController;
@FXML
private KnopfController knopfController;
public void initialize() {
model = new Model();
knopfController.setModel(model);
feldController.setModel(model);
}
}
您可以更进一步,并使用控制器工厂为您提供控制器模型。我在github repo中发布了一个这样做的例子。请注意,这只是概念验证:要像这样执行DI,您应该使用它的框架 - afterburner.fx提供一个简单但灵活的JavaFX DI框架(或者您可以使用其他标准的框架,如Spring或Guice)。