【问题标题】:JavaFX (with FXML) MVC: Model use ControllerJavaFX (with FXML) MVC: 模型使用控制器
【发布时间】:2017-06-29 21:23:48
【问题描述】:

我对 MVC 和 JavaFX 的概念还很陌生。 基本上我的游戏中有一些简单的动画。这是一个类比,可以更好地理解我的问题。

模型:model.java

public int fib(int n){
    ctrl.setLabelFib(n)
    someWaitFunction(1000 ms); //Now I can see the changes

    if (n <= 1) return n;
    else return fibonacci(n-1) + fibonacci(n-2);
}

控制器:ctrl.java

Label lFib = new Label();
public void setLabelFib(int n){
   lFib.setText(n)
}

查看:view.fxml

*Generate with Scene Builder*

如何在递归函数中访问控制器?还是我做错了?

【问题讨论】:

标签: java model-view-controller javafx model controller


【解决方案1】:

在实现Initializable 的控制器中,您将拥有@override method : initialize

在此您将创建您的模型:

model md = new model(); //depending of you constructor

要将控制器添加到模型中,您可以通过构造函数提供:

//in initialize of controller
model md = new model(this); 

//in you ctrl.java
private ctrl control;
public model(ctrl control){
    this.control = control
}

有了这个你就可以做到:

public int fib(int n){
    control.setLabelFib(n)
    Thread.sleep(1000);

    if (n <= 1) return n;
    else return fibonacci(n-1) + fibonacci(n-2);
}

我也写了等待的方法

尝试在评论中告诉它是如何工作的

【讨论】:

  • 有点用。我使用断点来查看标签是否在运行时发生变化。但只有在递归函数结束时,标签才变为正确的零。
  • @user3880174 因为Thread是“正常”的,模型无法实时实现场景,为了避免这种情况,Java创建了“Task”,在一个新的Thread中启动
  • 所以解决方法是创建一个任务。但是我该怎么做呢?
  • 一个任务只能使用一次,这不是你真正需要的你真的想打印你方法的所有值吗?
  • 模型不应该有任何对控制器的引用。
【解决方案2】:

模型不应该对控制器或视图有任何引用。您应该使模型的属性可观察,以便感兴趣的客户端(控制器或视图)可以观察它们并在它们发生变化时收到通知。

在 JavaFX 中定期更改 UI 的最佳方法是使用动画 API,例如Timeline

所以你可以这样做

private class FibonacciModel {

    private final IntegerProperty currentValue = new SimpleIntegerProperty(1);

    private int previous = 0 ;

    public IntegerProperty currentValueProperty() {
        return currentValue ;
    }

    public final int getCurrentValue() {
        return currentValueProperty().get();
    }

    public final void setCurrentValue(int value) {
        currentValueProperty().set(value);
    }

    public void nextValue() {
        int next = previous + getCurrentValue();
        previous = getCurrentValue();
        setCurrentValue(next);
    }
}

然后你的视图就可以了

public class FibonacciView extends VBox {

    private final Label label ;
    private final Button startButton  ;

    public FibonacciView(FibonacciModel model) {
        label = new Label();
        label.textProperty().bind(model.currentValueProperty().asString());

        FibonacciController controller = new FibonacciController(model);

        startButton = new Button("Start");
        startButton.setOnAction(e -> {
            startButton.setDisable(true);
            controller.animateNumbers(20)
                .setOnFinished(event -> startButton.setDisable(false));
        });

        getChildren().add(label, startButton);
    }
}

public class FibonacciController {

    private final FibonacciModel model ;

    public FibonacciController(FibonacciModel model) {
        this.model = model ;
    }

    public Animation animateNumbers(int howMany) {
        Timeline timeline = new Timeline(
            newKeyFrame(Duration.seconds(1), event -> model.nextValue());
        );
        timeline.setCycleCount(howMany);
        timeline.play();
        return timeline ;
    }
}

【讨论】:

    猜你喜欢
    • 2013-12-25
    • 2016-08-20
    • 2012-09-14
    • 2013-07-22
    • 2015-05-29
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多