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?

2
  • I think this will help or even be the solution : stackoverflow.com/questions/40117925/… Commented Feb 11, 2017 at 17:48
  • The model should not have any reference to either the view(s) or the controller(s). Commented Feb 12, 2017 at 0:41

2 Answers 2

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 ;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

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

5 Comments

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 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
So the solution is to create a task. But how can I do this?
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 ?
The model should not have any reference to the controller.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.