使用没有FXML的JavaFX控制器

Has*_*lah 3 java fxml javafx-8

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

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

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

Jam*_*s_D 14

您的问题对我来说并不是特别清楚:您只需创建课程,并将所有内容与听众联系起来.我不知道这是否有帮助,但这里有一个简单的例子,它只有几个文本字段和一个显示其总和的标签.这就是我认为的"经典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();
    }



}
Run Code Online (Sandbox Code Playgroud)

控制器:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

视图:

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<Integer>((Change c) -> {
            if (c.getControlNewText().matches("-?\\d*")) {
                return c ;
            }
            return null ;
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

申请类:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @hubbabubba 基本 API 设计。如果视图扩展了“GridPane”,则客户端代码可以将其实例分配给类型为“GridPane”的变量,例如“GridPane view = new AdditionView(...);”。这意味着我永远无法更改为使用不同的布局。布局应该是视图类的实现细节,而不是暴露给类的公共 API 的东西。我设置它的方式,我只保证它是某种“Parent”,所以我以后可以更改为使用不同的布局,而不会影响任何其他代码。 (6认同)
  • 这就是我所说的。在没有 FXML 的情况下在 JavaFX 上使用“经典 MVC”;谢谢,这很公平 (2认同)