0

I am fairly new to the concept of MVC and JavaFX. Basically I have game that have some simple animation in it. Here is a analogy for better understanding my problem.

Model: 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);
}

Controller: ctrl.java

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

View: view.fxml

*Generate with Scene Builder*

How can I access the controller in a recursive function? Or I am doing it completey wrong?

karel
  • 5,489
  • 46
  • 45
  • 50
  • I think this will help or even be the solution : http://stackoverflow.com/questions/40117925/javafx-many-static-fxml-controllers – GOXR3PLUS Feb 11 '17 at 17:48
  • The model should not have any reference to either the view(s) or the controller(s). – James_D Feb 12 '17 at 00:41

2 Answers2

1

Models should not have any reference to the controller(s), or to the view(s). You should make the properties of the model observable, so that interested clients (the controller or view) can observe them and receive notification when they change.

The best way to change the UI periodically in JavaFX is to use the Animation API, e.g. a Timeline.

So you can do

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);
    }
}

And then your view can do

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);
    }
}

and

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 ;
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322
0

In you controller which implements Initializable, you'll have the @override method : initialize

In this you'll create your model :

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

To add you controller to the model you can give in throught the constructor :

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

And

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

With this you'll be able to do :

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

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

I write the method to wait also

Try and tell in comment how it works

azro
  • 53,056
  • 7
  • 34
  • 70
  • It kind of worked. I used breakpoints to see if the label change in the run time. But only at the end of the recusive function the label changed to zero which is correct. – user3880174 Feb 11 '17 at 17:44
  • @user3880174 It's "normal" because of Thread, the model cannot actualize the scene in real time, to avois this, Java has created "Task" which is launched in a new Thread – azro Feb 11 '17 at 18:00
  • So the solution is to create a task. But how can I do this? – user3880174 Feb 11 '17 at 18:06
  • A Task can be used once, not sur it's really wht you need Do you really want to print all values of you method ? – azro Feb 11 '17 at 18:15
  • The model should not have any reference to the controller. – James_D Feb 12 '17 at 00:42