JavaFX - Timeline Animation Object not Displaying?

by meyer9168   Last Updated December 06, 2018 15:26 PM

I'm new to JavaFX, and I'm sure I'm missing something obvious here. I'm trying to make an animation of a car that travels from left to right across a window, wrapping around the right side when it gets there. The user should be able to hit up/down to adjust the speed of the animation. I had the animation going when I used a PathTransition object, but found out you can't adjust the Duration of a PathTransition, so I redid it in a Timeline.

With Timeline, though, I'm stuck. The car does not display on the screen when I launch the application. Here's what I'm hoping is a concise code snippet:

public class Project12 extends Application {

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

@Override
public void start(Stage primaryStage) {     
    //Create Pane to hold the car animation
    Pane pane = new Pane();

    //Create the RaceCarPane
    RaceCarPane raceCar = new RaceCarPane();
    pane.getChildren().add(raceCar); //Adds the race car to the main pane

    //Create the VBox to hold components
    VBox displayPane = new VBox();
    displayPane.getChildren().addAll(pane, userInstructions, btnPause);
    displayPane.setSpacing(15);
    displayPane.setAlignment(Pos.CENTER);

    //Create scene for display and add the display pane
    Scene scene = new Scene(displayPane);

    //Add the scene to the stage and display
    primaryStage.setTitle("Project 12");
    primaryStage.setResizable(false); //disable resizing of the window
    primaryStage.setScene(scene);
    primaryStage.show();

}

And the RaceCarPane:

public class RaceCarPane extends Pane {

    //Declare origin for determining polygon point locations
    private double originX = 10;
    private double originY = getHeight() - 10;
    private Timeline carAnimation;

    //Set the Timeline for the car in constructor method
    public RaceCarPane() {
        carAnimation = new Timeline(
                new KeyFrame(Duration.millis(100), e -> moveCar()));
        carAnimation.setCycleCount(Timeline.INDEFINITE);
        carAnimation.play();
    }

    private void paint() {

        //Create a polygon for the body 
        Polygon body = new Polygon();
        body.setFill(Color.BLUE);
        body.setStroke(Color.DARKBLUE);


        //Add points to the body
        ObservableList<Double> bodyList = body.getPoints();

        /*(code omitted, just adding coordinates to the ObservableList for all parts. 
        I don't believe the bug is here since it displayed when I was using a PathTransition animation)*/

        //Add to pane
        getChildren().addAll(body, roof, frontWheel, rearWheel);
    }

    public void setOrigin (double x, double y) {
        this.originX = x;
        this.originY = y;
    }

    @Override
    public void setWidth(double width) {
        super.setWidth(width);
        paint();
    }

    @Override
    public void setHeight(double height) {
        super.setHeight(height);;
        paint();
    }

    public void moveCar() {
        //Check that car is in bounds
        if(originX <= getWidth()) {
            originX += 10;
            paint();
        }
        else {
            originX = 0;
            paint();
        }

EDIT: Per @Jai's comment below, my solution was to revert to the PathTransition object and use its RateProperty bound to a SimpleDoubleProperty. While maybe not what the project was looking for as a solution, it does the trick, so I'm happy!

Tags : java javafx


Answers 2


It looks like you missed a closing brace in the paint method.

There are a few things "wrong". For one, you should not be creating new objects and adding them to the scene graph every time you want to move your car. You;ve also left out how you use originX, originY.

I suggest you use a Group to hold the parts of the car. Add it once to the RaceCarPane and use a transform on the group object to move it.

This would probably be easier if you based in on an AnimationTimer instead of a Timeline, particularly if you want to be able to dynamically adjust the speed of the car.

swpalmer
swpalmer
December 05, 2018 21:46 PM

@swpalmer was right to say that you shouldn't add it repeatedly.

That aside, you could definitely use PathTransition by using Animation.rateProperty() (PathTransition extends Animation).

Also, from PathTransition:

This Transition creates a path animation that spans its duration. The translation along the path is done by updating the translateX and translateY variables of the node, and the rotate variable will get updated if orientation is set to OrientationType.ORTHOGONAL_TO_TANGENT, at regular interval.

Therefore, if you are using Timeline, you should also be setting the translateX and translateY of the whole node (i.e. RaceCarPane) to perform the animation; trying to add polygons repeatedly is definitely the wrong approach. If you were also adding a lot of polygons when you were using PathTransition, you were probably not doing it quite right as well. Even when the animation turns out to be visually correct, it doesn't always mean that it is done correctly.

Jai
Jai
December 06, 2018 02:35 AM

Related Questions


JavaFX Preloader never called from main

Updated June 07, 2017 02:26 AM


can't get title bar on javafx program

Updated December 09, 2018 15:26 PM