使用没有FXML的JavaFX控制器

是否有可能在不使用FXML的情况下使用带有JavaFX GUI的控制器。

我注意到FXML文件包含一个fx-controller属性来绑定控制器,但我觉得它不是一个简单的方法来使用它。

有关在不使用FXML文件或JavaFX Scene Builder的情况下使用JavaFX创建MVC的任何想法?

你的问题对我来说并不是特别清楚:你只需要创建课程,并将所有内容与听众联系在一起。 我不知道这是否有帮助,但这里有一个简单的例子,它只有几个文本字段和一个显示其总和的标签。 这就是我所认为的“经典MVC”:如果模型发生变化,视图会观察模型并更新UI元素。 它将处理程序与UI元素一起注册,并在事件发生时委托给控制器:控制器依次处理输入(如果需要)并更新模型。

模型:

 package mvcexample; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ReadOnlyIntegerWrapper; import javafx.beans.property.SimpleIntegerProperty; public class AdditionModel { private final IntegerProperty x = new SimpleIntegerProperty(); private final IntegerProperty y = new SimpleIntegerProperty(); private final ReadOnlyIntegerWrapper sum = new ReadOnlyIntegerWrapper(); public AdditionModel() { sum.bind(x.add(y)); } public final IntegerProperty xProperty() { return this.x; } public final int getX() { return this.xProperty().get(); } public final void setX(final int x) { this.xProperty().set(x); } public final IntegerProperty yProperty() { return this.y; } public final int getY() { return this.yProperty().get(); } public final void setY(final int y) { this.yProperty().set(y); } public final javafx.beans.property.ReadOnlyIntegerProperty sumProperty() { return this.sum.getReadOnlyProperty(); } public final int getSum() { return this.sumProperty().get(); } } 

控制器:

 package mvcexample; public class AdditionController { private final AdditionModel model ; public AdditionController(AdditionModel model) { this.model = model ; } public void updateX(String x) { model.setX(convertStringToInt(x)); } public void updateY(String y) { model.setY(convertStringToInt(y)); } private int convertStringToInt(String s) { if (s == null || s.isEmpty()) { return 0 ; } if ("-".equals(s)) { return 0 ; } return Integer.parseInt(s); } } 

视图:

 package mvcexample; import javafx.geometry.HPos; import javafx.geometry.Pos; import javafx.scene.Parent; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.control.TextFormatter; import javafx.scene.control.TextFormatter.Change; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; public class AdditionView { private GridPane view ; private TextField xField; private TextField yField; private Label sumLabel; private AdditionController controller ; private AdditionModel model ; public AdditionView(AdditionController controller, AdditionModel model) { this.controller = controller ; this.model = model ; createAndConfigurePane(); createAndLayoutControls(); updateControllerFromListeners(); observeModelAndUpdateControls(); } public Parent asParent() { return view ; } private void observeModelAndUpdateControls() { model.xProperty().addListener((obs, oldX, newX) -> updateIfNeeded(newX, xField)); model.yProperty().addListener((obs, oldY, newY) -> updateIfNeeded(newY, yField)); sumLabel.textProperty().bind(model.sumProperty().asString()); } private void updateIfNeeded(Number value, TextField field) { String s = value.toString() ; if (! field.getText().equals(s)) { field.setText(s); } } private void updateControllerFromListeners() { xField.textProperty().addListener((obs, oldText, newText) -> controller.updateX(newText)); yField.textProperty().addListener((obs, oldText, newText) -> controller.updateY(newText)); } private void createAndLayoutControls() { xField = new TextField(); configTextFieldForInts(xField); yField = new TextField(); configTextFieldForInts(yField); sumLabel = new Label(); view.addRow(0, new Label("X:"), xField); view.addRow(1, new Label("Y:"), yField); view.addRow(2, new Label("Sum:"), sumLabel); } private void createAndConfigurePane() { view = new GridPane(); ColumnConstraints leftCol = new ColumnConstraints(); leftCol.setHalignment(HPos.RIGHT); leftCol.setHgrow(Priority.NEVER); ColumnConstraints rightCol = new ColumnConstraints(); rightCol.setHgrow(Priority.SOMETIMES); view.getColumnConstraints().addAll(leftCol, rightCol); view.setAlignment(Pos.CENTER); view.setHgap(5); view.setVgap(10); } private void configTextFieldForInts(TextField field) { field.setTextFormatter(new TextFormatter((Change c) -> { if (c.getControlNewText().matches("-?\\d*")) { return c ; } return null ; })); } } 

申请类:

 package mvcexample; import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; public class MVCExample extends Application { @Override public void start(Stage primaryStage) { AdditionModel model = new AdditionModel(); AdditionController controller = new AdditionController(model); AdditionView view = new AdditionView(controller, model); Scene scene = new Scene(view.asParent(), 400, 400); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

我广泛使用JavaFX,不使用FXML或scenebuilder。 所以我可以保证它可以做到。

下面是我的IDE为获取JavaFX主类而生成的自动生成的代码。 这将是您的应用程序的根。 然后,您将添加它以创建您的应用程序。

 public class NewFXMain extends Application { @Override public void start(Stage primaryStage) { Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); Scene scene = new Scene(root, 300, 250); primaryStage.setTitle("Hello World!"); primaryStage.setScene(scene); primaryStage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } }