-1

I have the following Problem.

I'm am a complete newbie in JavaFX and I am trying to code a Game of Life program.

I have a class "MainView" extending VBox. MainView has an ArrayList "playingField" of the class Field as an attribute, consisting of cells and also a draw() method, which draws rectangles on a Canvas, according to the states of the cells.

Inside of Field I have a transition() method, which changes the state of the cells, according to some defined transition rules.

This is working fine, and I can manually progress by clicking on a button on my primary stage. What I want though, is a possibility to press a button once, and then have indefinite steps of progresses -> applications of the transition()-method and redrawings of the canvas.

If I try to do it in a loop, it works just fine, but of course happens way to fast to recognize the single steps, but when I use Thread.sleep(), the whole application freezes.

I know I have to solve this with either a timeline or a transitions, but I can't really find sufficient informations online on how to inegrate the transition() and draw() methods in an infinite cycle in either one of them.

I hope following snippets will help to make myself more clear:

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
    try {
        
        MainView mainView = new MainView();

        
        Scene scene = new Scene(mainView, 1000, 1032);
        primaryStage.setScene(scene);
        primaryStage.show();
        mainView.draw();
        
    } catch(Exception e) {
        e.printStackTrace();
    }
}



public static void main(String[] args) {
    launch(args);
}

}

public MainView() extends VBox {
    private Button stepButton;
    private Canvas canvas;
    private Field playingField;

    this.stepButton = new Button("progress");
    this.stepButton.setOnAction(ActionEvent -> {
        playingField.fieldTransition();
        draw();
    });

    public void draw() {

    //drawing Rectangles that represent the cells of field on a canvas
        }
    }
}

Field class with the transitions() method:

public class Field implements TransitionRules {

public void fieldTransition(){
    //method to change the state of the cells according to given rules.
    }
}
ouflak
  • 2,458
  • 10
  • 44
  • 49
Gray Fox
  • 9
  • 5
  • 3
    The Animation API is the easiest way to do this, probably with a [`Timeline`](https://openjfx.io/javadoc/16/javafx.graphics/javafx/animation/Timeline.html). Just define a keyframe with an event handler that updates the UI. Can you explain where you are actually stuck? – James_D Feb 08 '22 at 16:31
  • "methods in an infinite cycle" -> set the cycle count to [INDEFINITE](https://openjfx.io/javadoc/17/javafx.graphics/javafx/animation/Animation.html#INDEFINITE). – jewelsea Feb 08 '22 at 16:38
  • I simply cant find ressources that tell me how to structure the Keyframes and such. All the sources I find handle simple rectangles or other single shapes. – Gray Fox Feb 08 '22 at 17:05
  • the KeyValue expects a start and and end value, but in my case I have the ArrayList playing field, then I have to call the method playingField.fieldTransition and then I have to draw the whole field again with mainView.field. I dont want the UI updated on a single event. I want to press a button once, and then I want that the UI updates itself indefininetly often (or until stopped) according to the new states of the ArrayList playingField. – Gray Fox Feb 08 '22 at 17:16
  • You don't need a `KeyValue`. Just create the `KeyFrame` with a time (`Duration`) and an event handler. If I understand your requirements correctly, you can use the same event handler you already posted. Then add the `KeyFrame` to a `Timeline` and play the timeline with `INDEFINITE` cycle count. – James_D Feb 08 '22 at 17:27
  • This seems like a duplicate of https://stackoverflow.com/a/60685975/2189127, but again it's not really clear where you're stuck. – James_D Feb 08 '22 at 17:39
  • @James_D Oh man, thank you I made it, thanks to your "approach" or more like solution. – Gray Fox Feb 08 '22 at 19:15

1 Answers1

1

Thank you guys, I made it work.

In mainView I defined a method

        public void progress() {
        field.fieldTransition();
        draw();
    }

And then in Main I did this:

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
    try {
        
        MainView mainView = new MainView();
        
        Scene scene = new Scene(mainView, 1000, 1032);
        primaryStage.setScene(scene);
        primaryStage.show();
        Timeline timeline = new Timeline();
        KeyFrame frame1 = new KeyFrame(Duration.seconds(1.0), e -> mainView.progress());
        timeline.getKeyFrames().add(frame1);
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
        mainView.draw();
        
    } catch(Exception e) {
        e.printStackTrace();
    }
}

Im pretty sure I added some unnecessary detours and I'll probably have to work on it much more, but for the first time I made the automatic progress happen.

Also thanks to @James_D for pointing out the other JavaFX-Thread. I didn't find it by myself, but it seems very useful and I will come back to it in the future.

I know for some of you guys its pretty basic to make stuff like this work, but I just started a few days ago with JavaFX and its mechanics are still somewhat confusing for me.

Gray Fox
  • 9
  • 5